Generic Spring Data JPA repository implementation to load data by class type
hibernate, java, spring, spring-data-jpa
Solution
You have to add mapping for BaseEntity as well:
<class name="xxx.BaseEntity " abstract="true">
You can also try to use annotations and just set packagesToScan property
Problem
I am using Spring Data JPA 1.4.3.RELEASE with Hibernate 4.2.7.Final I was able to successfully create a Base Repository class, something on the lines of : http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/repositories.html#repositories.custom-behaviour-for-all-repositories ``` @NoRepositoryBean public interface BaseRepository <T extends BaseEntity, ID extends Serializable> extends JpaRepository<T, ID> @NoRepositoryBean public class BaseRepositoryImpl<T extends BaseEntity, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> { ``` I am able to sucessfully work with : ``` public interface FlowerRepository extends BaseRepository<Flower, Long> { ``` Now, I am trying to write an generic implementation(that extends the base repository) to load all reference data like Flower types. That is because I do not want to have a repository for every single "type" data or "reference" data. I want to be able to manage that using a generic repository by passing a specific "class" type(that implements a interface specific to reference data type).For E-g ``` loadAll(FlowerType.class) ``` I use HBMs to map hibernate entities so I have : ``` <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="xxx.FlowerType" table="FLWTYP"> <meta attribute="extends" inherit="false">xxx.BaseReferenceType</meta> <id name="primaryKey" type="string"> <column name="TYP_CDE" length="5" /> <generator class="assigned" /> </id> public class FlowerType extends BaseReferenceType<String> implements ReferenceEntity<String> public abstract class BaseReferenceEntity<T extends Serializable> extends BaseEntity implements ReferenceEntity<T> public abstract class BaseEntity implements DomainEntity public interface ReferenceEntity<PK extends Serializable> { ``` Persistence XML : ``` <?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="xxxPU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" /> <property name="hibernate.hbm2ddl.auto" value="none" /> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" /> <property name="hibernate.connection.charSet" value="UTF-8" /> <property name="hibernate.jdbc.batch_size" value="100" /> <property name="hibernate.show_sql" value="false" /> <property name="hibernate.format_sql" value="false" /> <property name="hibernate.transaction.flush_before_completion" value="false" /> <property name="hibernate.connection.autocommit" value="false" /> <property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml"/> <property name="jadira.usertype.autoRegisterUserTypes" value="true" /> <property name="jadira.usertype.databaseZone" value="jvm" /> <property name="jadira.usertype.javaZone" value="jvm" /> </properties> </persistence-unit> </persistence> ``` Hibernate config : ``` <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <mapping resource="FlowerType.hbm.xml"/> <mapping resource="Flower.hbm.xml"/> </session-factory> </hibernate-configuration> ``` So I looked at some tutorial links and SO posts and did some work based on : Spring Jpa adding custom functionality to all repositories and at the same time other custom funcs to a single repository I have : ``` @NoRepositoryBean public interface CustomReferenceDataRepository<T extends BaseEntity & ReferenceEntity<PK>, PK extends Serializable> { public Map<PK, T> findAll(Class<T> clz); } public interface ReferenceDataRepository extends BaseRepository, CustomReferenceDataRepository { } public class ReferenceDataRepositoryImpl<T extends BaseEntity & ReferenceEntity<PK>, PK extends Serializable> implements CustomReferenceDataRepository<T, PK> { @PersistenceContext private EntityManager em; @Override public Map<PK, T> findAll(Class<T> clz) { //do whatever return null; } } ``` Ended up with a exception : ``` Caused by: java.lang.IllegalArgumentException: Not an managed type: class xxx.BaseEntity at org.hibernate.ejb.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:200) ~[hibernate-entitymanager-4.2.7.Final.jar:4.2.7.Final] at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:68) ~[spring-data-jpa-1.4.3.RELEASE.jar:na] at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65) ~[spring-data-jpa-1.4.3.RELEASE.jar:na] at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:146) ~[spring-data-jpa-1.4.3.RELEASE.jar:na] ``` I understand Hibernate does not manage "BaseEntity" but am not able to figure out what I am missing. Is my requirement of implementing a generic repository for reference data even possible ? If yes, what am I doing wrong ? Any guidance appreciated. Thanks.