Reputation: 5543
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:
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)
Upvotes: 1
Views: 6249
Reputation: 2018
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:
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 ...
.findBy
prefix before.Since this is not clear from docs I've created the issue in Spring Data Commons
issue tracker.
Upvotes: 2
Reputation: 6073
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.
Upvotes: 1