I have Spring microservicies application using hexagonal architecture. When try to get data from my H2 database using hql query I have an exception which say my Entity is not mapped. My Entity is subclass of another one who have commons attribute.
package com.package.infrastructure.repository.jpa.entity.nomenclature;
import lombok.Data;
import javax.persistence.*;
@Data
@MappedSuperclass
public class NomenclatureEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 50)
private String label;
}
Activity
package com.package.company.infrastructure.repository.jpa.entity.nomenclature;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.persistence.Entity;
@Data
@EqualsAndHashCode
@ToString
@Entity(name = "N_ACTIVITY")
public class ActivityEntity extends NomenclatureEntity {
}
repository
package com.package.company.infrastructure.repository.jpa;
import com.package.company.infrastructure.repository.jpa.entity.nomenclature.NomenclatureEntity;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface NomenclatureSpringDataRepository extends CrudRepository<NomenclatureEntity, Long> {
}
Spring data implementation
package com.package.company.infrastructure.repository.jpa;
import com.package.company.core.NomenclatureRepository;
import com.package.company.core.model.nomenclature.*;
import com.package.company.infrastructure.repository.jpa.entity.nomenclature.*;
import com.package.company.infrastructure.repository.jpa.mapping.nomenclature.*;
import org.mapstruct.factory.Mappers;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;
import java.util.stream.Collectors;
@Transactional(readOnly = true)
public class NomenclatureRepositorySpringDataWrapper implements NomenclatureRepository {
NomenclatureSpringDataRepository nomenclatureSpringDataRepository;
@PersistenceContext
private EntityManager entityManager;
public NomenclatureRepositorySpringDataWrapper(NomenclatureSpringDataRepository nomenclatureSpringDataRepository) {
this.nomenclatureSpringDataRepository = nomenclatureSpringDataRepository;
}
@Override
public List<Activity> getAllActivity() {
Query query = entityManager.createQuery("SELECT a FROM ActivityEntity a");
List<ActivityEntity> activityEntities = query.getResultList();
ActivityEntityMapper mapper = Mappers.getMapper(ActivityEntityMapper.class);
List<Activity> activities = activityEntities.stream().map(ae->mapper.toNomenclature(ae)).collect(Collectors.toList());
return activities;
}
}
start class
package com.package;
import com.package.core.NomenclatureRepository;
import com.package.core.model.nomenclature.*;
import com.package.infrastructure.config.CompanyApplicationConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
@SpringBootApplication(exclude={SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
@Import(value = MyApplicationConfig.class)
public class MyApplication {
@Autowired
private NomenclatureRepository nomenclatureRepository;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Bean
public CommandLineRunner init(){
return (String... args)->{
nomenclatureRepository.saveActivity(new Activity(1L, "Activity 1"));
nomenclatureRepository.saveActivity(new Activity(2L, "Activity 2"));
};
}
}
Result
2021-07-01 10:29:08.118 ERROR 9224 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: ActivityEntity is not mapped [SELECT a FROM ActivityEntity a]] with root cause
org.hibernate.hql.internal.ast.QuerySyntaxException: ActivityEntity is not mapped
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:169) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:91) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
You have used @Entity(name = "N_ACTIVITY")
to class ActivityEntity
. The name in @Entity
is for JPA-QL queries, it defaults to the class name if no value is provided, but since you changed it you have to make sure you use this name when building queries.
So either your query should be updated as follows:
SELECT a FROM N_ACTIVITY a
or you can remove the name and use the class name ActivityEntity