JPA No property findAll found for type Product - spring

My repository:
#Repository
public interface ProductDao extends JpaRepository<Product,Long>,JpaSpecificationExecutor<Product> {
Page<Product> findAll(Specification<Product> specification,Pageable pageable);
}
My service:
...
#Autowired
public ProductServiceImpl(ProductRepository repository, ProductDao productDao, ProductImgService productImgService, ProductClassService productClassService, AuthUserService authUserService, DeviceService deviceService){
super(repository);
this.productDao = productDao;
this.productImgService = productImgService;
this.productClassService = productClassService;
this.authUserService = authUserService;
this.deviceService = deviceService;
}
final
ProductDao productDao;
...
I use it in the service like this:
midResult = productDao.findAll((root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> list = new ArrayList<>();
list.add(criteriaBuilder.equal(root.get("ouId").as(Long.class),product.getOuId()));
if(product.getPclassId()!=null)
list.add(criteriaBuilder.equal(root.get("pclassId").as(Long.class),product.getPclassId()));
if(product.getProductStatus()!=null)
list.add(criteriaBuilder.equal(root.get("productStatus").as(Integer.class),product.getProductStatus()));
if(product.getProductName()!=null)
list.add(criteriaBuilder.equal(root.get("productName").as(String.class),product.getProductName()));
if(product.getCreator()!=null)
list.add(criteriaBuilder.equal(root.get("creator").as(Integer.class),product.getCreator()));
list.add(criteriaBuilder.between(root.get("createTimeTmp").as(Long.class),Long.parseLong(finalStarttsp),Long.parseLong(finalEndtsp)));
Predicate[] p = new Predicate[list.size()];
criteriaQuery.where(criteriaBuilder.and(list.toArray(p)));
return criteriaQuery.getRestriction();
}, pageable);
The Product Class definition is good .
And when I run this code , error turned out to be :
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property findAll found for type Product!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:247) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:398) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:378) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:86) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.PartTreeMybatisQuery.<init>(PartTreeMybatisQuery.java:81) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.MybatisQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(MybatisQueryLookupStrategy.java:71) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.MybatisQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(MybatisQueryLookupStrategy.java:120) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.MybatisQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(MybatisQueryLookupStrategy.java:50) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:436) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:221) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.support.MybatisRepositoryFactoryBean.afterPropertiesSet(MybatisRepositoryFactoryBean.java:64) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
I'm using springboot and there's no config like #EnableJpaRepositories
But it don't seems to be necessary cause other repository is good .

You are using spring-data in incorrect way. When you write method findAll in repository, it will look for given attribute in entity.
For example, you have an entity User with attribute firstName. Then you can defined method like, findByFirstName.
In given example, spring-data looking for attribute all which is not available as a part of Product.
In this case, you need to write your own query using #Query annotation.
BTW, what you want to achieve?

It works like this for me:
#NonNull
Page<Product> findAll(#Nullable Specification<Product> specification, #NonNull Pageable pageable);

Related

CucumberBackendException: No qualifying bean of type

When trying to run step defs with abstract class contains all the context configuration spring sees 2 differnt beans parent and stepdef
I'm using spring boot version: 2.6.4 , with Junit 5 and cucumber version 7.2.3
#SpringBootTest(classes = CoreApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = AbstractIntegrationTest.Config.class)
#CucumberContextConfiguration
public abstract class AbstractIntegrationTest implements En {}
#Suite
#IncludeEngines("cucumber")
#SelectClasspathResource("com/example/bdd")
#ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example.bdd")
public class CucumberIntegrationTest {
}
public class MyStepdefs extends AbstractIntegrationTest{
public MyStepdefs() {
When("^client post to \"([^\"]*)\" with valid data$", (String arg0) -> {
});
Then("^the client receives status code of (\\d+)$", (Integer arg0) -> {
});
}
}
Exception Stack trace:
io.cucumber.core.backend.CucumberBackendException: No qualifying bean of type 'com.orange.ces.core.bdd.AbstractIntegrationTest' available: expected single matching bean but found 2: com.orange.ces.core.bdd.MyStepdefs,com.orange.ces.core.bdd.AbstractIntegrationTest
at io.cucumber.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:124)
at io.cucumber.spring.TestContextAdaptor.stop(TestContextAdaptor.java:107)
at io.cucumber.spring.SpringFactory.stop(SpringFactory.java:161)
at io.cucumber.core.runner.Runner.disposeBackendWorlds(Runner.java:156)
at io.cucumber.core.runner.Runner.runPickle(Runner.java:78)
at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:128)
at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$3(CucumberExecutionContext.java:151)
at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:151)
at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:128)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:249)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:110)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:199)
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1632)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:111)
at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:82)
at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
at io.cucumber.core.cli.Main.run(Main.java:87)
at io.cucumber.core.cli.Main.main(Main.java:30)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.orange.ces.core.bdd.AbstractIntegrationTest' available: expected single matching bean but found 2: com.orange.ces.core.bdd.MyStepdefs,com.orange.ces.core.bdd.AbstractIntegrationTest
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1271)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at io.cucumber.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:120)
... 30 more
In case you have several step definition classes, you can create a stub class with annotations only
#ContextConfiguration(classes = AbstractIntegrationTest.Config.class)
#CucumberContextConfiguration
public class StubConfig { }
Place it into a separate package and mention it in #CucumberOptions (if you have it)
Another ugly workaround:(

How can I fix bugs in Custom Repository?

I'm trying to make a Custom Repository with spring-data-jpa.
My codes
Repository
#NoRepositoryBean
interface CustomRepository<T, ID : Serializable> : JpaRepository<T, ID> {
fun findBySomeRestrict(id: ID): T?
}
RepositoryImpl
#Transactional(readOnly = true)
class CustomRepositoryImpl<T, ID : Serializable>(
private val entityManager: EntityManager,
jpaEntityInformation: JpaMetamodelEntityInformation<T, ID>
) : SimpleJpaRepository<T, ID>(jpaEntityInformation, entityManager), CustomRepository<T, ID> {
override fun findBySomeRestrict(id: ID): T? {
// TODO
}
}
Main class
#EnableJpaAuditing
#EnableJpaRepositories(repositoryBaseClass = CustomRepositoryImpl::class)
#SpringBootApplication
class ForSubmitApplication
fun main(args: Array<String>) {
runApplication<ForSubmitApplication>(*args)
}
MyErrorMessage
Caused by: java.lang.IllegalStateException: No suitable constructor found on interface com.example.forsubmit.global.custom.CustomRepository to match the given arguments: org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation, jdk.proxy2.$Proxy132. Make sure you implement a constructor taking these
at org.springframework.data.repository.core.support.RepositoryFactorySupport.lambda$instantiateClass$6(RepositoryFactorySupport.java:578) ~[spring-data-commons-2.6.0.jar:2.6.0]
at java.base/java.util.Optional.orElseThrow(Optional.java:403) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.instantiateClass(RepositoryFactorySupport.java:578) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepositoryViaReflection(RepositoryFactorySupport.java:542) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:182) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:164) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:75) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:324) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:322) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:230) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.util.Lazy.get(Lazy.java:114) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:328) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:144) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.13.jar:5.3.13]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.13.jar:5.3.13]
... 72 common frames omitted
What I do to fix it
Change the type of constructor to JpaEntityInformation
Decompile the code
It seems you only want to provide the implementation of one method.
In that case you must not set repositoryBaseClass.
Instead you want to follow the steps outlined in the documentation.
Create an interface just containing the custom method(s). You currently don't have that.
Create an implementation of it. You are currently implementing the final Repository interface which is wrong.
Extend your final repository interface from the custom interface created in step 1.

Spring Data Elasticsearch cusom repository

In my Spring Boot application I'm trying to implement a fuzzy search via Elasticsearch.
This is my ES config:
#Profile("test")
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.example.domain.repository.elasticsearch")
public class ElasticsearchTestConfig {
}
I have a repository:
#Repository
public interface ESDecisionRepository extends ElasticsearchRepository<ESDecision, String>, ESDecisionRepositoryCustom {
}
In order to be able to do a fuzzy search I have created a custom repository:
public interface ESDecisionRepositoryCustom {
public List<ESDecision> findFuzzyBySearchTerm(String searchTerm);
}
and provided a custom implementation:
#Repository
public class ESDecisionRepositoryCustomImpl implements ESDecisionRepositoryCustom {
#Autowired
protected ElasticsearchTemplate elasticsearchTemplate;
#Override
public List<ESDecision> findFuzzyBySearchTerm(String searchTerm) {
Criteria c = new Criteria("name").fuzzy(searchTerm);
return elasticsearchTemplate.queryForList(new CriteriaQuery(c), ESDecision.class);
}
}
Right now during startup my application fails with a following exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ESDecisionRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property searchTerm found for type ESDecision!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 43 common frames omitted
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property searchTerm found for type ESDecision!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:247)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:398)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:378)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:89)
at org.springframework.data.elasticsearch.repository.query.ElasticsearchPartQuery.<init>(ElasticsearchPartQuery.java:44)
at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory$ElasticsearchQueryLookupStrategy.resolveQuery(ElasticsearchRepositoryFactory.java:119)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:436)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:221)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263)
at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactoryBean.afterPropertiesSet(ElasticsearchRepositoryFactoryBean.java:67)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
... 53 common frames omitted
What am I doing wrong and how to fix it ?
Change your custom repository implementation class name from ESDecisionRepositoryCustomImpl to ESDecisionRepositoryImpl.
From the docs
The most important bit for the class to be found is the Impl postfix of the name on it compared to the core repository interface (see below).
There is a naming convention that has to be followed to make the custom repository implementation work. Check out the docs
Try this:
#Repository
public class ESDecisionRepositoryCustomImpl implements ESDecisionRepositoryCustom {
#Autowired
protected ElasticsearchTemplate elasticsearchTemplate;
#Override
public List<ESDecision> findFuzzyBySearchTerm(String searchTerm) {
Criteria c = new Criteria("name").fuzzy(searchTerm);
return elasticsearchTemplate.queryForList(new CriteriaQuery(c), ESDecision.class);
}
}
Hope this helps.

How do you use both Spring Data JPA and Spring Data Elasticsearch repositories on the same domain class in a Spring Boot application?

I'm trying to use both Spring Data JPA and Spring Data Elasticsearch on the same domain object but it doesn't work.
When I tried to run a simple test, I got the following exception:
org.springframework.data.mapping.PropertyReferenceException: No
property index found for type Person! at
org.springframework.data.mapping.PropertyPath.(PropertyPath.java:75)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.Part.(Part.java:76)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree$OrPart.(PartTree.java:235)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:373)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree$Predicate.(PartTree.java:353)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree.(PartTree.java:84)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.PartTreeJpaQuery.(PartTreeJpaQuery.java:61)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:95)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:206)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:73)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.(RepositoryFactorySupport.java:408)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:206)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] ... 43 common frames
omitted
They work when disabling either one.
The project is based on Spring Boot 1.3.0.M5.
This is a sample project reproducing the situation:
https://github.com/izeye/spring-boot-throwaway-branches/tree/data-jpa-and-elasticsearch
Repositories in Spring Data are datasource agnostic, meaning that JpaRepository and ElasticsearchRepository both roll up into Repository interface. When this is the case, then auto-configuration of Spring Boot will cause Spring Data JPA to try and configure a bean for each repository in the project that inherits any Spring Data Commons base repository.
To fix this problem you need to move your JPA repository and Elasticsearch repository to separate packages and make sure to annotate your #SpringBootApplication application class with:
#EnableJpaRepositories
#EnableElasticsearchRepositories
Then you need to specify where the repositories are for each enable annotation. This ends up looking like:
#SpringBootApplication
#EnableJpaRepositories("com.izeye.throwaway.data")
#EnableElasticsearchRepositories("com.izeye.throwaway.indexing")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Then your application will be able to disambiguate which repositories are intended for which Spring Data project.
You can use like this:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
#EnableElasticsearchRepositories(includeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
public class DataConfiguration {
...
}
Or in SpringBoot:
#SpringBootApplication
#EnableJpaRepositories(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
#EnableElasticsearchRepositories(includeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
public class MyApplication {
...
}

How to create repository for more than one entity?

I'm trying to create a simple web-site, which hosts topics and comments. I've begun with topics, and created repository for them:
package com.myProject.mvc3.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface TopicRepository extends CrudRepository<Topic, Integer>{
public List<Topic> findAllByTopicTag(Tag currentTag);
}
And I've defined the path for my repository in the servlet-context.xml:
jpa:repositories base-package="com.myProject.mvc3.repository"
Now, I'd like to include the comments in my repository, and the following code doesn't work:
package com.myProject.mvc3.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CommentRepository extends CrudRepository<Comment, Integer> {
public List<Comment> findTopicComments(Topic topic);
}
My project doesn't build even. Can you give me an advice, how to create repositories for more than one entities (Topic class and Comment class are declared with #Entity)?
What i'm faciong:
there is HDD pic on the TopicRepository class icon
there is a question mark on the CommentRepository class icon
error log (a huge one):
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'topicController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.epam.mvc3.service.CommentService com.epam.mvc3.controller.TopicController.commentService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'commentService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.epam.mvc3.repository.CommentRepository com.epam.mvc3.service.CommentService.commentRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'commentRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: No property find found for type class com.epam.mvc3.model.Comment
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:467)
org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:483)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:358)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:325)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
javax.servlet.GenericServlet.init(GenericServlet.java:160)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:84)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:298)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
java.lang.Thread.run(Thread.java:722)
Just add By in findTopicComments so that it became findByTopicComments. Of course, this will work only if Comment entity has topicComments field or it has topic field which, in turn, has comments field.
Btw, you don't need #Repository annotation on Spring-data-jpa repositories.
Actually, if your query name doesn't match pattern ^(find|read|get)(\\p{Upper}.*?)??By from this class then the following occurs:
any of the prefixes such as get, 'read' and find won't be stripped and will be considered as the part of a JPQL query to generate. In this case you will get an exception:
java.lang.IllegalArgumentException: No property find found for type class ....
if there's nothing to strip from your method name then it will be processed as if it had findBy prefix before.
Since this is not clear from docs I've created the issue in Spring Data Commons issue tracker.
Try to write your repositories in such way:
#Repository
public interface TopicRepository extends JpaRepository<Topic, Integer> >{
#Query("select topic from Topic topic where topic.topicTag.id=?1")
public List<Topic> findAllByTopicTag(int topicTagId);
}
#Repository
public interface CommentRepository extends JpaRepository<Comment, Integer> {
#Query("select comment from Comment comment where comment.topic.id=?1")
public List<Comment> findTopicComments(int topicId);
}
In this example I specify id of the entities as search criteria because usually they are used as foreign key. You can easily add additional search criteria if you need.
More details about query methods in Spring Data you can find in reference documentation.
Update
About your error stack trace - I think this error means that you don't specify your classes in persistent.xml.
There is also a way to not specify all classes in your persistent.xml -> look here and here for details.
Also with Spring you can easily configure your JPA project without persistent.xml file if you use full java config. For example:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean factoryBean =
new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan(new String[] {"com.dimasco.springjpa.domain"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
//vendorAdapter.setGenerateDdl(generateDdl)
factoryBean.setJpaVendorAdapter(vendorAdapter);
Properties additionalProperties = new Properties();
additionalProperties.put("hibernate.hbm2ddl.auto", "update");
factoryBean.setJpaProperties(additionalProperties);
return factoryBean;
}
As you can see in this example I simply define what packages to scan.

Resources