Introduction to Spring Data JPA
The Spring Data JPA, a sub project of Spring Data is aimed at simplifying repository implementations. Repositories typically provide Create, Read, Update and Delete (CRUD) operations for domain objects. In this blog post, I will show how Spring Data JPA drastically reduces the effort needed to create repositories.
We will be using HSQLDB as the database and Hibernate as the JPA implementation provider. Here is a complete list project’s dependencies from Maven’s pom.xml file:
<dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.1.0.RELEASE</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>2.1_3</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.2a</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.1.2.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.1.0.Final</version> </dependency> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.2.8</version> </dependency> </dependencies>
Before we go about implementing repositories using Spring Data JPA, let’s create two domain objects Person and Address:
package com.inflinx.blog.springdata.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="PERSON") public class Person { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="PERSON_ID") private Long id; @Column(name="FIRST_NAME") private String firstName; @Column(name="LAST_NAME") private String lastName; @Column(name="GENDER_CODE") private String genderCode; // Getters and Setters }
package com.inflinx.blog.springdata.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name="ADDRESS") public class Address { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="ADDRESS_ID") private int id; @Column(name="STREET") private String street; @Column(name="CITY") private String city; @Column(name="STATE") private String state; @Column(name="ZIPCODE") private int zipCode; @ManyToOne @JoinColumn(name="PERSON_ID") private Person person; // Getters and Setters }
Notice that the two domain classes have JPA annotations such as @Table and @Column that map these classes to relational tables. Also notice the Many To One relationship between Address and Person classes.
Simple JPA Repository
We now start by creating a Spring Data JPA repository for the Person class. This involves creating a repository interface as shown below. The PersonRepository interface extends the Spring Data JPA’s Repository marker interface and has one finder method. The findOne method follows Spring Data JPA’s naming convention for retrieving an entity using its ID.
package com.inflinx.blog.springdata.repository; import org.springframework.data.repository.Repository; import com.inflinx.blog.springdata.domain.Person; public interface PersonRepository extends Repository < Person, Long > { public Person findOne(Long id); }
Traditionally, we would also create an implementation class for this repository. However Spring Data JPA alleviates this need and provides an implementation class (proxy) automatically at runtime. For this to happen, we add the jpa:repositories bean declaration to our context file. Here is the complete context file:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:repository="http://www.springframework.org/schema/data/repository" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.1.xsd http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:schema.sql"/> <jdbc:script location="classpath:test-data.sql"/> </jdbc:embedded-database> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:data-source-ref="dataSource" p:persistence-xml-location="classpath:test-persistence.xml" p:jpaDialect-ref="jpaDialect"> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entity-manager-factory-ref="entityManagerFactory"> </bean> <jpa:repositories base-package="com.inflinx.blog.springdata.repository" /> </beans>
The jdbc:embedded-database tag in the context file starts an in-memory database using HSQLDB and creates a datasource for it. The schema.sql file shown below has the DDL commands for creating the Person and Address table:
CREATE TABLE PERSON (PERSON_ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, FIRST_NAME VARCHAR(256), LAST_NAME VARCHAR(256), GENDER_CODE VARCHAR(1)); CREATE TABLE ADDRESS(ADDRESS_ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, STREET VARCHAR(256), CITY VARCHAR(100), STATE VARCHAR(10), ZIPCODE INT, PERSON_ID INT, FOREIGN KEY (PERSON_ID) REFERENCES PERSON(PERSON_ID));
The test-data.sql file has the test data we will be using to test our repositories:
INSERT INTO PERSON (FIRST_NAME, LAST_NAME, GENDER_CODE) VALUES ('John', 'Doe', 'M'); INSERT INTO PERSON (FIRST_NAME, LAST_NAME, GENDER_CODE) VALUES ('Jane', 'Doe', 'F'); INSERT INTO PERSON (FIRST_NAME, LAST_NAME, GENDER_CODE) VALUES ('Joe', 'Bloggs', 'M');
The entitiyManagerFactory bean uses test-persistence.xml file that has the standard JPA configuration.
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="springdata" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>com.inflinx.blog.springdata.domain.Person</class> <class>com.inflinx.blog.springdata.domain.Address</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> </properties> </persistence-unit> </persistence>
This completes all the setup needed for creating a Spring Data JPA repository. Now let’s create a JUnit test class to test our implementation.
package com.inflinx.blog.springdata.repository; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; import org.springframework.transaction.annotation.Transactional; import com.inflinx.blog.springdata.domain.Person; @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) @Transactional @ContextConfiguration(locations = {"classpath:test-context.xml"}) public class PersonRepositoryTest { @Autowired private PersonRepository personRepository; @Test public void testPerson() { Person person = personRepository.findOne(1L); Assert.assertNotNull(person); System.out.println("First Name: " + person.getFirstName()); } }
Notice that we are simply injecting the PersonRepository implementation into the test. When you run the class, you should see that test has passed and “First Name: Jane” in your console.
CRUD JPA Repository
The above PersonRepository has only one finder method and might not be ideal for most real world cases. To address this, Spring Data JPA provides an aptly named CrudRepository interface that extends Repository interface and adds persistence, finder and delete methods. The table below lists some of the available CrudRepository methods:
save(S entity) | Saves a given entity |
save(Iterable entities) | Saves all the given entities |
findOne(ID id) | Retrieves an entity by its id |
exists(ID id) | Checks if a given entity exists |
findAll | Returns all the entities |
count | Returns the number of all the entities |
delete(ID id) | Deletes an entity with the given id |
delete(T entity) | Delets a given entity |
A new person repository interface that uses CrudRepository is given below.
package com.inflinx.blog.springdata.repository; import org.springframework.data.repository.CrudRepository; import com.inflinx.blog.springdata.domain.Person; public interface PersonCrudRepository extends CrudRepository < Person, Long > { }
Here is a JUnit test that tests the above repository:
package com.inflinx.blog.springdata.repository; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.transaction.annotation.Transactional; import com.inflinx.blog.springdata.domain.Person; @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({DependencyInjectionTestExecutionListener.class}) @Transactional @ContextConfiguration(locations = {"classpath:test-context.xml"}) public class PersonCrudRepositoryTest { @Autowired private PersonCrudRepository personRepository; @Test @Rollback(false) public void testCreate() { Person p = new Person(); p.setFirstName("Test"); p.setLastName("Data"); p.setGenderCode("M"); p = personRepository.save(p); Assert.assertNotNull(p.getId()); System.out.println("Created Id: " + p.getId()); } }
Custom Finder Methods
Spring Data JPA makes it very easy to add new finder methods to repositories. For example, let’s say we want to retrieve all persons with a given last name. Here is the modified PersonCrudRepository repository with the new finder method:
package com.inflinx.blog.springdata.repository; import java.util.List; import org.springframework.data.repository.CrudRepository; import com.inflinx.blog.springdata.domain.Person; public interface PersonCrudRepository extends CrudRepository < Person, Long > { public List< Person > findByLastName(String lastName); }
The convention for these finder methods is simply findByMemberName. It is also possible to combine multiple members into one finder method. So, findByLastNameAndFirstName(String lastName, String firstName) will find all persons with the given first name and last name.
Here is the JUnit test class to test the findByLastName method:
@Test public void testFindByLastName() { List< Person > lastNameList = personRepository.findByLastName("Doe"); Assert.assertEquals(2, lastNameList.size()); }
Named Queries
The out of the box CRUD methods are sufficient for most cases. However, there are times where we might want to execute custom SQL Queries to retrieve data. For example, let’s say we want to count all the persons that have a given last name. To address such situations, Spring Data JPA provides a @Query annotation. Here is the new person repository with the @Query annotated method:
package com.inflinx.blog.springdata.repository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import com.inflinx.blog.springdata.domain.Person; public interface PersonCrudRepository extends CrudRepository < Person, Long > { @Query("select count(p) from Person p where p.lastName = ?1") public Long getLastNameCount(String lastName); }
Here is a test method for the above Query method:
@Test public void testGetLastNameCount() { Long count = personRepository.getLastNameCount("Doe"); Assert.assertEquals(2L, count.longValue()); }
Custom Repository Implementation
For cases, where the out of the box repository implementations are not enough, Spring Data JPA makes it easy to provide custom implementations that would still integrate with the generic repository abstraction. To see this in action, let’s implement a custom Address repository. We start with a custom interface that declares the additional functionality.
package com.inflinx.blog.springdata.repository; public interface AddressRepositoryCustom { public Long someRandomMethod(); }
The next step is to create a class that implements the custom functionality.
package com.inflinx.blog.springdata.repository.jpa; import com.inflinx.blog.springdata.repository.AddressRepositoryCustom; public class AddressRepositoryImpl implements AddressRepositoryCustom { public Long someRandomMethod() { return 143L; } }
Finally, we create the AddressRepository interface that extends the custom interface as shown below:
public interface AddressRepository extends CrudRepository < Address, Long >, AddressRepositoryCustom { }
Here is a test class that tests the custom method implementation:
package com.inflinx.blog.springdata.repository; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({DependencyInjectionTestExecutionListener.class}) @Transactional @ContextConfiguration(locations = {"classpath:test-context.xml"}) public class AddressRepositoryCustomTest { @Autowired private AddressRepository personRepository; @Test public void testSomeMethod() { Assert.assertEquals(143L, personRepository.someRandomMethod().longValue()); } }
Spring Data JPA requires that you follow strict naming conventions when creating custom repository implementation (unless you provide additional configuration). For example, if the repository interface is AddressRepository, then the name of the custom interface should be AddressRepositoryCustom. If you don’t follow this convention, you will end up with errors similar to this:
Caused by: java.lang.IllegalArgumentException: Could not create query metamodel for method public abstract java.lang.Long com.inflinx.blog.springdata.repository.AddressRepositoryCustom.someRandomMethod()!
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:92)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:162)
Thanks for very nice tutorial !!!
I have following problem. I hope you can help me. When I trying crud operation using service layer its giving me bean creation error. Its working fine if I do operation through ‘personRepository’. please help.my code is as follows
public class PersonRepositoryTest {
@Autowired
private PersonService personService; // ITS NOT WORKING
// private PersonRepository personRepository; // ITS WORKING
@Test
public void testSavePerson(){
Person person = new Person();
person.setFirstName(“Ramkumar”);
person.setLastName(“Patel”);
personService.save(person);
}
}
@Bharat,
What is the error you are getting? Can you post the exception?
@Sudha Belida
I guess I am doing something wrong in configuration. please find below link for full source code : –
https://www.box.com/s/n11ewh6supw37novb9um
and the exception as follows….
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘com.bharat.patel.repository.PersonRepositoryTest’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bharat.patel.service.PersonService com.bharat.patel.repository.PersonRepositoryTest.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bharat.patel.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bharat.patel.service.PersonService com.bharat.patel.repository.PersonRepositoryTest.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bharat.patel.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
… 32 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bharat.patel.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:952)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
… 34 more
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 9.952 sec <<< FAILURE!
05.10.2012 18:41:53 *INFO * GenericApplicationContext: doClose – Closing org.springframework.context.support.GenericApplicationContext@3a7faad6: startup date [Fri Oct 05 18:41:44 BST 2012]; root of context hierarchy – (AbstractApplicationContext.java, line 1025)
05.10.2012 18:41:53 *INFO * DefaultListableBeanFactory: destroySingletons – Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4cedd1e2: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,dataSource,entityManagerFactory,jpaDialect,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,personRepository,org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#0,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy – (DefaultSingletonBeanRegistry.java, line 433)
05.10.2012 18:41:53 *INFO * LocalContainerEntityManagerFactoryBean: destroy – Closing JPA EntityManagerFactory for persistence unit 'SpringData-Jpa' – (AbstractEntityManagerFactoryBean.java, line 441)
Results :
Tests in error:
testSavePerson(com.bharat.patel.repository.PersonRepositoryTest): Error creating bean with name 'com.bharat.patel.repository.PersonRepositoryTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bharat.patel.service.PersonService com.bharat.patel.repository.PersonRepositoryTest.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bharat.patel.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Tests run: 2, Failures: 0, Errors: 1, Skipped: 0
@Sudha Belida
please find below source code for full source code.
https://www.box.com/s/s0u2il480gawc6qm6ry4
The exception I got is..
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘com.bharat.patel.repository.PersonRepositoryTest’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bharat.patel.service.PersonService com.bharat.patel.repository.PersonRepositoryTest.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bharat.patel.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bharat.patel.service.PersonService com.bharat.patel.repository.PersonRepositoryTest.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bharat.patel.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
… 32 more
Thanks for your help in advance
@bharat
I noticed that you forgot to add this to your appContext.xml file:
<context:component-scan base-package=”com.bharat.patel.service” />
Try this and it should fix your issue.
Thanks Sudha,
I found the solution.
It was and the correct base package should be.
please delete duplicate comments by me on your blog.
Anyways thanks for your help such a nice tutorial !!!
Hi My Service interface and implementation are in different packages. So in that case what can be done?
Nice tutorial can you show a snapshot of the packaging structure, in a maven spring project i am trying to load the applicationContext-test.xml from another package(src/test/resoucres) it is not loading.
Hi
I am new to spring JPA. Could you please provide an example if i want to retrieve data from multiple tables instead of one table? In that case how to create domain objects and establaish the relation between them.
Nice article 🙂 Thanks !
great tutorial, many thanks 🙂