Hi,
I am having a particular issue that doesn't want to go away.
I have created a Custom Repository that handles dynamic search in my own custom way. See the code below
The implementation is adapted from a custom search I built in the Jpa 1.x days. I am still comfortable with it.Code:@NoRepositoryBean public interface BaseRepository<T, ID extends Serializable, Q extends BaseEntityQueryCriteria> extends JpaRepository<T, ID>, Serializable { List<T> criteriaSearch( Q entityCriteria); }
the factory bean isCode:class BaseRepositoryImpl<T, ID extends Serializable, Q extends BaseEntityQueryCriteria> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID, Q> { @Resource private EntityManager entityManager; /** * EMPTY_STRING */ //private final static String EMPTY_STRING = " "; /** * PRIMARY_ENTITY */ private final String PRIMARY_ENTITY = "{PRIMARY_ENTITY}"; // public BaseRepositoryImpl() { // } /** * constructor */ public BaseRepositoryImpl(Class<T> entityClass, EntityManager _entityManager) { super(entityClass, _entityManager); //set this entitymanager this.entityManager = _entityManager; } @SuppressWarnings("unchecked") @Override public List<T> criteriaSearch( Q entityCriteria) { String queryString = buildQuery(entityCriteria); Query query = entityManager.createQuery(queryString); setQueryParameter(query, entityCriteria.getParameters()); return query.getResultList(); } /** * * */ private String buildQuery(BaseQueryCriteria baseQueryBuilder) { String entityName = baseQueryBuilder.getEntityName(); String sqlScript = baseQueryBuilder.getSqlString(); sqlScript = sqlScript.replace(PRIMARY_ENTITY, entityName); baseQueryBuilder = null; return sqlScript; } /** * sets the various parameters on the JPQL using the map that is passed in. * * @param Query - the query object to be set * @Map - parameters */ private void setQueryParameter(Query query, Map<String, Object> parameters) { Set<String> keySet = parameters.keySet(); if (keySet.size() > 0) { for (String placeHolder : keySet) { Object object = parameters.get(placeHolder); if (object instanceof String) { object = ((String) object).toLowerCase(); } query.setParameter(placeHolder, object); } } } }
The problem now is that I have a repository interface that extends BaseRepository like thisCode:public class BaseRepositoryFactoryBean<R extends JpaRepository<T, ID>, T, ID extends Serializable> extends JpaRepositoryFactoryBean<R, T, ID> { @Override protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { return new MyRepositoryFactory(entityManager); } /** * * @param <T> * @param <I> */ private static class MyRepositoryFactory<T, ID extends Serializable, Q extends BaseEntityQueryCriteria> extends JpaRepositoryFactory { /** * */ private EntityManager entityManager; /** * constructor * * @param entityManager */ public MyRepositoryFactory(EntityManager entityManager) { super(entityManager); this.entityManager = entityManager; } @Override protected Object getTargetRepository(RepositoryMetadata metadata) { return new BaseRepositoryImpl<T, ID, Q>((Class<T>) metadata.getDomainType(), entityManager); } @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { // The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory //to check for QueryDslJpaRepository's which is out of scope. return BaseRepositoryImpl.class; } } }
However, a call to storeRepo.criteriaSearch(new StoreQueryCriteria())Code:@Repository public interface StoreRepo extends BaseRepository<Store, Integer, StoreQueryCriteria> { }
throws the exception
Code:Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'storeRepo': FactoryBean threw exception on object creation; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property criteria found for type com.okmich.storeruns.common.entity.Store at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:149) at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102) at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1441) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:305) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83) at StoreTest.main(StoreTest.java:22) Caused by: org.springframework.data.mapping.PropertyReferenceException: No property criteria found for type com.okmich.storeruns.common.entity.Store at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:74) at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:326) at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:352) at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:306) at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270) at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:244) at org.springframework.data.repository.query.parser.Part.<init>(Part.java:73) at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:180) at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:260) at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:240) at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:68) at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:57) at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:90) at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:162) at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:68) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:280) at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:148) at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:125) at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:41) at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142) ... 10 more
I know this has to do with the Query Derivation strategy. However, for my case I want to override it or better still have a fine grain control so as to prevent derivation of query for this custom method.
How do I do this? I have googled for a clue but no way so far.
Regards.


Reply With Quote