1. Introduction
Spring Data is a part of Spring Framework. It simplifies the data access process for both relational and non-relational databases. Java Persistence API (JPA) is Java’s standard API specification for object-relational mapping. Spring Data JPA is a part of Spring Data and it supports Hibernate 5, OpenJPA 2.4, and EclipseLink 2.6.1.
Spring Data repository significantly reduces the amount of boilerplate code required to implement data access layers for various persistence stores. Spring Data JpaRepository interface extends CrudRepository and provides finder methods out of the box.
In this example, I will demonstrate how to use Spring Data JpaRepository to create, update, delete, and search contact data in a relational database.
2. Technologies Used
The example code in this article was built and run using:
- Java 1.8.101 (1.8.x will do fine)
- Maven 3.3.9 (3.3.x will do fine)
- Eclipse Mars (Any Java IDE would work)
- Spring data 1.5.10.RELEASE
- Hibernate 5.0.12.Final
- H2 1.4.196
3. Spring Boot JPA Project
Spring Boot Starters provides more than 30 starters to ease the dependency management for your project. The easiest way to generate a Spring Boot JPA with Hibernate project is via Spring starter tool with the steps below:
- Go to
https://start.spring.io/
- Select
Maven Project
with Java
and Spring Boot version 1.5.10 and Add both JPA
and H2
in the “search for dependencies” - Enter the group name as
jcg.zheng.demo
and artifact as jpademo
- Click the
Generate Project
button
A maven project will be generated and downloaded to your workstation. Import it into your Eclipse workspace.
3.1 POM
The generated pom.xml
includes H2
and spring-boot-starter-data-jpa
, which uses Hibernate as the implementation of JPA.
pom.xml
01 | <? xml version = "1.0" encoding = "UTF-8" ?> |
04 | < modelVersion >4.0.0</ modelVersion > |
06 | < groupId >jcg.zheng.demo</ groupId > |
07 | < artifactId >spring-jparepository-demo</ artifactId > |
08 | < version >0.0.1-SNAPSHOT</ version > |
09 | < packaging >jar</ packaging > |
11 | < name >spring-jparepository-demo</ name > |
12 | < description >Demo Spring Data JPA Application</ description > |
15 | < groupId >org.springframework.boot</ groupId > |
16 | < artifactId >spring-boot-starter-parent</ artifactId > |
17 | < version >1.5.10.RELEASE</ version > |
22 | < project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding > |
23 | < project.reporting.outputEncoding >UTF-8</ project.reporting.outputEncoding > |
24 | < java.version >1.8</ java.version > |
30 | < groupId >org.springframework.boot</ groupId > |
31 | < artifactId >spring-boot-starter-data-jpa</ artifactId > |
35 | < groupId >com.h2database</ groupId > |
36 | < artifactId >h2</ artifactId > |
37 | < scope >runtime</ scope > |
41 | < groupId >org.springframework.boot</ groupId > |
42 | < artifactId >spring-boot-starter-test</ artifactId > |
51 | < groupId >org.springframework.boot</ groupId > |
52 | < artifactId >spring-boot-maven-plugin</ artifactId > |
3.2 JPA Demo Application
The generated JpaDemoApplication.java
is annotated with @SpringBootApplication
. It is equivalent to use @Configuration
, @EnableAutoConfiguration
, and @ComponentScan
with their default attributes.
We will annotate it with @EnableJpaRepositories
. It enables Spring to scan the base package and all its sub-packages for any interfaces extending Repository
or one of its sub-interfaces. For each interface found, Spring creates the appropriate bean to handle invocation of the query methods.
We will configure several Spring Beans to manage transactions in the H2
datasource.
JpaDemoApplication.java
01 | package jcg.zheng.demo.jpademo; |
03 | import javax.persistence.EntityManagerFactory; |
04 | import javax.sql.DataSource; |
06 | import org.springframework.boot.SpringApplication; |
07 | import org.springframework.boot.autoconfigure.SpringBootApplication; |
08 | import org.springframework.context.annotation.Bean; |
09 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; |
10 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; |
11 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; |
12 | import org.springframework.orm.jpa.JpaTransactionManager; |
13 | import org.springframework.orm.jpa.JpaVendorAdapter; |
14 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; |
15 | import org.springframework.orm.jpa.vendor.Database; |
16 | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; |
19 | @EnableJpaRepositories (basePackages = "jcg.zheng.demo.jpademo" ) |
20 | public class JpaDemoApplication { |
22 | public static void main(String[] args) { |
23 | SpringApplication.run(JpaDemoApplication. class , args); |
27 | public DataSource dataSource() { |
28 | return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build(); |
32 | public JpaVendorAdapter jpaVendorAdapter() { |
33 | HibernateJpaVendorAdapter bean = new HibernateJpaVendorAdapter(); |
34 | bean.setDatabase(Database.H2); |
35 | bean.setGenerateDdl( true ); |
36 | bean.setShowSql( true ); |
41 | public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, |
42 | JpaVendorAdapter jpaVendorAdapter) { |
43 | LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean(); |
44 | bean.setDataSource(dataSource); |
45 | bean.setJpaVendorAdapter(jpaVendorAdapter); |
46 | bean.setPackagesToScan( "jcg.zheng.demo.jpademo" ); |
51 | public JpaTransactionManager transactionManager(EntityManagerFactory emf) { |
52 | return new JpaTransactionManager(emf); |
Note: Configure four Spring Beans – dataSource
, jpaVendorAdapter
, entityManagerFactory
, transactionManager
to manage the transactions.
4. Domains
In this step, we will create two domains – Contact
and ContactNote
. Use the JPA annotations to map them to two tables in a database. These two tables have a one-to-many relationship.
4.1 Contact
The Contact
entity class is mapped to CONTACT
table in the database. All the fields are mapped to columns with the @Column
annotation.
Contact.java
001 | package jcg.zheng.demo.jpademo.entity; |
003 | import java.util.ArrayList; |
004 | import java.util.List; |
006 | import javax.persistence.CascadeType; |
007 | import javax.persistence.Column; |
008 | import javax.persistence.Entity; |
009 | import javax.persistence.EnumType; |
010 | import javax.persistence.Enumerated; |
011 | import javax.persistence.FetchType; |
012 | import javax.persistence.GeneratedValue; |
013 | import javax.persistence.Id; |
014 | import javax.persistence.OneToMany; |
015 | import javax.persistence.Table; |
017 | import jcg.zheng.demo.jpademo.type.PhoneType; |
020 | @Table (name = "CONTACT" ) |
021 | public class Contact { |
028 | @Column (name = "First_Name" ) |
029 | private String firstName; |
031 | @Column (name = "Last_Name" ) |
032 | private String lastName; |
034 | @Column (name = "Email" ) |
035 | private String email; |
037 | @Column (name = "Phone_Number" ) |
038 | private String phoneNumber; |
040 | @Column (name = "Phone_Type" ) |
041 | @Enumerated (EnumType.STRING) |
042 | private PhoneType phoneType; |
044 | @OneToMany (mappedBy= "contact" , cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Contact_Note. class ) |
050 | public Contact(String firstName, String lastName, String email, PhoneType phoneType, String phone) { |
052 | this .firstName = firstName; |
053 | this .lastName = lastName; |
055 | this .phoneType = phoneType; |
056 | this .phoneNumber = phone; |
059 | public Long getId() { |
063 | public String getFirstName() { |
067 | public void setFirstName(String firstName) { |
068 | this .firstName = firstName; |
071 | public String getLastName() { |
075 | public void setLastName(String lastName) { |
076 | this .lastName = lastName; |
079 | public String getEmail() { |
083 | public void setEmail(String email) { |
087 | public void setId(Long id) { |
091 | public String getPhoneNumber() { |
095 | public void setPhoneNumber(String phoneNumber) { |
096 | this .phoneNumber = phoneNumber; |
099 | public PhoneType getPhoneType() { |
103 | public void setPhoneType(PhoneType phoneType) { |
104 | this .phoneType = phoneType; |
107 | public List getNotes() { |
108 | if ( this .notes == null ) { |
109 | this .notes = new ArrayList<>(); |
114 | public void addNote(Contact_Note note){ |
115 | getNotes().add(note); |
116 | note.setContact( this ); |
119 | public void setNotes(List addresses) { |
120 | this .notes = addresses; |
4.2 Contact Note
The Contact_Note
entity class is mapped to Contact_Note
table in the database. Each contact can have many contact notes.
Contact_Note.java
01 | package jcg.zheng.demo.jpademo.entity; |
03 | import javax.persistence.Entity; |
04 | import javax.persistence.GeneratedValue; |
05 | import javax.persistence.Id; |
06 | import javax.persistence.JoinColumn; |
07 | import javax.persistence.ManyToOne; |
10 | public class Contact_Note { |
16 | private String message; |
19 | @JoinColumn (name = "CONTACT_ID" ) |
20 | private Contact contact; |
22 | public Contact_Note() { |
30 | public void setId(Long id) { |
34 | public Contact getContact() { |
38 | public void setContact(Contact contact) { |
39 | this .contact = contact; |
42 | public String getMessage() { |
46 | public void setMessage(String message) { |
47 | this .message = message; |
4.3 Phone Type
Phone type is defined as an enum and is mapped to the Phone_type
column in the CONTACT
table.
PhoneType.java
1 | package jcg.zheng.demo.jpademo.type; |
4 | OFFICE, HOME, MOBILE, OTHER; |
5. ContactRepository
The repository interface must extend Repository
and be typed to the domain class and an ID type. In this step, we will annotate ContactRepository
with @Repository
and extend it from JpaRepository
along with the Contact
domain and its ID
type. It serves two purposes:
- By extending
JpaRepository
we get a bunch of generic CRUD methods to create, update, delete, and find contacts. - It allows Spring to scan the
classpath
for this interface and create a Spring bean for it.
ContactRepository.java
01 | package jcg.zheng.demo.jpademo.repository; |
05 | import org.springframework.data.jpa.repository.JpaRepository; |
06 | import org.springframework.data.jpa.repository.Query; |
07 | import org.springframework.data.repository.query.Param; |
08 | import org.springframework.stereotype.Repository; |
09 | import org.springframework.transaction.annotation.Transactional; |
11 | import jcg.zheng.demo.jpademo.entity.Contact; |
12 | import jcg.zheng.demo.jpademo.type.PhoneType; |
16 | public interface ContactRepository extends JpaRepository<Contact, Long> { |
18 | @Query ( "SELECT con FROM Contact con WHERE con.phoneType=(:pType) AND con.lastName= (:lName)" ) |
19 | List findByLastNameAndPhoneType( @Param ( "pType" ) PhoneType pType, @Param ( "lName" ) String lName); |
We will create ContactRepositoryTest
which utilizes SpringRunner
and @DataJpaTest
to demonstrate that ContactRepository
can create, update, delete, and find contacts with just a few lines of code.
ContactRepositoryTest.java
001 | package jcg.zheng.demo.jpademo.repository; |
003 | import static org.junit.Assert.assertEquals; |
004 | import static org.junit.Assert.assertNull; |
006 | import java.util.List; |
008 | import org.junit.Test; |
009 | import org.junit.runner.RunWith; |
010 | import org.springframework.beans.factory.annotation.Autowired; |
011 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; |
012 | import org.springframework.test.context.junit4.SpringRunner; |
014 | import jcg.zheng.demo.jpademo.entity.Contact; |
015 | import jcg.zheng.demo.jpademo.entity.Contact_Note; |
016 | import jcg.zheng.demo.jpademo.type.PhoneType; |
018 | @RunWith (SpringRunner. class ) |
020 | public class ContactRepositoryTest { |
023 | private ContactRepository contactRepo; |
026 | public void it_can_find_the_contact_after_save_it() { |
027 | Contact contact = new Contact( "Mary" , "Zheng" , "test@test.com" , PhoneType.HOME, "6365272943" ); |
028 | Contact_Note note = new Contact_Note(); |
029 | note.setMessage( "She is a java geek" ); |
030 | contact.addNote(note); |
032 | contactRepo.save(contact); |
034 | List contacts = contactRepo.findAll(); |
036 | assertEquals( 1 , contacts.size()); |
037 | assertEquals( "Mary" , contacts.get( 0 ).getFirstName()); |
038 | assertEquals( "Zheng" , contacts.get( 0 ).getLastName()); |
039 | assertEquals( "test@test.com" , contacts.get( 0 ).getEmail()); |
040 | assertEquals(PhoneType.HOME, contacts.get( 0 ).getPhoneType()); |
041 | assertEquals( "6365272943" , contacts.get( 0 ).getPhoneNumber()); |
042 | assertEquals( 1 , contacts.get( 0 ).getNotes().size()); |
043 | assertEquals( "She is a java geek" , contacts.get( 0 ).getNotes().get( 0 ).getMessage()); |
047 | public void it_can_delete_the_contact_after_save_it() { |
048 | Contact contact = new Contact( "Mary" , "Zheng" , "test@test.com" , PhoneType.HOME, "6365272943" ); |
049 | Contact_Note note = new Contact_Note(); |
050 | note.setMessage( "She is a java geek" ); |
051 | contact.addNote(note); |
053 | contactRepo.save(contact); |
055 | List foundContacts = contactRepo.findAll(); |
057 | contactRepo.delete(foundContacts.get( 0 )); |
059 | List contacts = contactRepo.findAll(); |
060 | assertEquals( 0 , contacts.size()); |
065 | public void it_can_update_the_contact_after_save_it() { |
066 | Contact contact = new Contact( "Mary" , "Zheng" , "test@test.com" , PhoneType.HOME, "6365272943" ); |
068 | contactRepo.save(contact); |
070 | contact.setEmail( "mary.zheng@test.com" ); |
071 | contactRepo.save(contact); |
073 | List contacts = contactRepo.findAll(); |
074 | assertEquals( 1 , contacts.size()); |
075 | assertEquals( "mary.zheng@test.com" , contacts.get( 0 ).getEmail()); |
080 | public void it_can_find_contacts_by_name_and_type() { |
082 | contactRepo.save( new Contact( "Mary" , "Zheng" , "mary.zheng@jcg.org" , PhoneType.HOME, "6368168164" )); |
083 | contactRepo.save( new Contact( "Tom" , "Smith" , "tom.smith@jcg.org" , PhoneType.MOBILE, "(636) 527-2943" )); |
084 | contactRepo.save( new Contact( "John" , "Joe" , "john.joe@jcg.org" , PhoneType.OFFICE, "(314) 527 2943" )); |
085 | contactRepo.save( new Contact( "Cindy" , "Chang" , "cindy.change@jcg.org" , PhoneType.OTHER, "404-789-1456" )); |
087 | List contactsWithZheng = contactRepo.findByLastNameAndPhoneType(PhoneType.HOME, "Zheng" ); |
089 | assertEquals( 1 , contactsWithZheng.size()); |
090 | Contact foundContact = contactsWithZheng.get( 0 ); |
091 | assertEquals( "Mary" , foundContact.getFirstName()); |
092 | assertEquals( "Zheng" , foundContact.getLastName()); |
093 | assertEquals( "mary.zheng@jcg.org" , foundContact.getEmail()); |
094 | assertEquals(PhoneType.HOME, foundContact.getPhoneType()); |
095 | assertEquals( "6368168164" , foundContact.getPhoneNumber()); |
096 | assertEquals( 0 , foundContact.getNotes().size()); |
100 | public void it_return_null_when_not_found(){ |
101 | Contact found = contactRepo.findOne(2L); |
6. Demo Time
Execute the Junit tests to confirm that the ContactRepository
is working as expected.
6.1 Save
it_can_find_the_contact_after_save_it output
01 | 2018-03-08 19:21:55.074 INFO 5024 --- [ main] j.z.d.j.r.ContactRepositoryTest : Starting ContactRepositoryTest on SL2LS431841 with PID 5024 (started by Shu.Shan in C:\MZheng_Java_workspace\Java Code Geek Examples\spring-jparepository-demo) |
02 | 2018-03-08 19:21:55.076 INFO 5024 --- [ main] j.z.d.j.r.ContactRepositoryTest : No active profile set , falling back to default profiles: default |
03 | 2018-03-08 19:21:55.104 INFO 5024 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7671cb68: startup date [Thu Mar 08 19:21:55 CST 2018]; root of context hierarchy |
04 | 2018-03-08 19:21:55.544 INFO 5024 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version |
05 | 2018-03-08 19:21:55.545 INFO 5024 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'dataSource' with a different definition: replacing [Root bean: class [null]; scope=; abstract= false ; lazyInit= false ; autowireMode=3; dependencyCheck=0; autowireCandidate= true ; primary= false ; factoryBeanName=jpaDemoApplication; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in jcg.zheng.demo.jpademo.JpaDemoApplication] with [Root bean: class [org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceFactoryBean]; scope=; abstract= false ; lazyInit= false ; autowireMode=0; dependencyCheck=0; autowireCandidate= true ; primary= false ; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] |
06 | 2018-03-08 19:21:56.184 INFO 5024 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url= 'jdbc:h2:mem:b7b1d620-048e-4b5e-9675-3c3fd4742c3e;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false' , username= 'sa' |
07 | 2018-03-08 19:21:56.703 INFO 5024 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' |
08 | 2018-03-08 19:21:56.724 INFO 5024 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ |
11 | 2018-03-08 19:21:56.894 INFO 5024 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} |
12 | 2018-03-08 19:21:56.898 INFO 5024 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found |
13 | 2018-03-08 19:21:56.900 INFO 5024 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist |
14 | 2018-03-08 19:21:56.985 INFO 5024 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} |
15 | 2018-03-08 19:21:57.211 INFO 5024 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect |
16 | 2018-03-08 19:21:57.988 INFO 5024 --- [ main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update |
17 | 2018-03-08 19:21:58.029 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT |
18 | 2018-03-08 19:21:58.030 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT |
19 | 2018-03-08 19:21:58.038 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note |
20 | 2018-03-08 19:21:58.040 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note |
21 | 2018-03-08 19:21:58.121 INFO 5024 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' |
22 | 2018-03-08 19:21:58.503 INFO 5024 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory |
23 | 2018-03-08 19:21:58.975 INFO 5024 --- [ main] j.z.d.j.r.ContactRepositoryTest : Started ContactRepositoryTest in 4.345 seconds (JVM running for 5.428) |
24 | 2018-03-08 19:21:59.035 INFO 5024 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_find_the_contact_after_save_it@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@65b97f47]; rollback [ true ] |
25 | Hibernate: call next value for hibernate_sequence |
26 | Hibernate: call next value for hibernate_sequence |
27 | Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) |
28 | Hibernate: insert into Contact_Note (CONTACT_ID, message, id ) values (?, ?, ?) |
29 | Hibernate: select contact0_.ID as ID1_0_, contact0_.Email as Email2_0_, contact0_.First_Name as First_Na3_0_, contact0_.Last_Name as Last_Nam4_0_, contact0_.Phone_Number as Phone_Nu5_0_, contact0_.Phone_Type as Phone_Ty6_0_ from CONTACT contact0_ |
30 | 2018-03-08 19:21:59.317 INFO 5024 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_find_the_contact_after_save_it@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]. |
31 | 2018-03-08 19:21:59.329 INFO 5024 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7671cb68: startup date [Thu Mar 08 19:21:55 CST 2018]; root of context hierarchy |
32 | 2018-03-08 19:21:59.337 INFO 5024 --- [ Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' |
- Line 28-29: two Insert statements
6.2 Update
it_can_update_the_contact_after_save_it output
01 | 2018-03-08 19:24:43.821 INFO 18416 --- [ main] j.z.d.j.r.ContactRepositoryTest : Starting ContactRepositoryTest on SL2LS431841 with PID 18416 (started by Shu.Shan in C:\MZheng_Java_workspace\Java Code Geek Examples\spring-jparepository-demo) |
02 | 2018-03-08 19:24:43.822 INFO 18416 --- [ main] j.z.d.j.r.ContactRepositoryTest : No active profile set , falling back to default profiles: default |
03 | 2018-03-08 19:24:43.846 INFO 18416 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7671cb68: startup date [Thu Mar 08 19:24:43 CST 2018]; root of context hierarchy |
04 | 2018-03-08 19:24:44.327 INFO 18416 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version |
05 | 2018-03-08 19:24:44.328 INFO 18416 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'dataSource' with a different definition: replacing [Root bean: class [null]; scope=; abstract= false ; lazyInit= false ; autowireMode=3; dependencyCheck=0; autowireCandidate= true ; primary= false ; factoryBeanName=jpaDemoApplication; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in jcg.zheng.demo.jpademo.JpaDemoApplication] with [Root bean: class [org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceFactoryBean]; scope=; abstract= false ; lazyInit= false ; autowireMode=0; dependencyCheck=0; autowireCandidate= true ; primary= false ; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] |
06 | 2018-03-08 19:24:44.992 INFO 18416 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url= 'jdbc:h2:mem:be0f302a-c332-4e7a-9d25-83126b6dcb66;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false' , username= 'sa' |
07 | 2018-03-08 19:24:45.520 INFO 18416 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' |
08 | 2018-03-08 19:24:45.544 INFO 18416 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ |
11 | 2018-03-08 19:24:45.698 INFO 18416 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} |
12 | 2018-03-08 19:24:45.703 INFO 18416 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found |
13 | 2018-03-08 19:24:45.705 INFO 18416 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist |
14 | 2018-03-08 19:24:45.811 INFO 18416 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} |
15 | 2018-03-08 19:24:46.051 INFO 18416 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect |
16 | 2018-03-08 19:24:46.834 INFO 18416 --- [ main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update |
17 | 2018-03-08 19:24:46.868 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT |
18 | 2018-03-08 19:24:46.869 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT |
19 | 2018-03-08 19:24:46.878 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note |
20 | 2018-03-08 19:24:46.879 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note |
21 | 2018-03-08 19:24:46.966 INFO 18416 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' |
22 | 2018-03-08 19:24:47.286 INFO 18416 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory |
23 | 2018-03-08 19:24:47.689 INFO 18416 --- [ main] j.z.d.j.r.ContactRepositoryTest : Started ContactRepositoryTest in 4.281 seconds (JVM running for 5.307) |
24 | 2018-03-08 19:24:47.754 INFO 18416 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_update_the_contact_after_save_it@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@3c5dbdf8]; rollback [ true ] |
25 | Hibernate: call next value for hibernate_sequence |
26 | Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) |
27 | Hibernate: update CONTACT set Email=?, First_Name=?, Last_Name=?, Phone_Number=?, Phone_Type=? where ID=? |
28 | Hibernate: select contact0_.ID as ID1_0_, contact0_.Email as Email2_0_, contact0_.First_Name as First_Na3_0_, contact0_.Last_Name as Last_Nam4_0_, contact0_.Phone_Number as Phone_Nu5_0_, contact0_.Phone_Type as Phone_Ty6_0_ from CONTACT contact0_ |
29 | 2018-03-08 19:24:47.910 INFO 18416 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_update_the_contact_after_save_it@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]. |
30 | 2018-03-08 19:24:47.913 INFO 18416 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7671cb68: startup date [Thu Mar 08 19:24:43 CST 2018]; root of context hierarchy |
31 | 2018-03-08 19:24:47.916 INFO 18416 --- [ Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' |
- Line 27: Update statement
6.3 Delete
it_can_delete_the_contact_after_save_it output
01 | 2018-03-08 19:25:54.514 INFO 13708 --- [ main] j.z.d.j.r.ContactRepositoryTest : Started ContactRepositoryTest in 4.379 seconds (JVM running for 5.38) |
02 | 2018-03-08 19:25:54.573 INFO 13708 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_delete_the_contact_after_save_it@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@3c5dbdf8]; rollback [ true ] |
03 | Hibernate: call next value for hibernate_sequence |
04 | Hibernate: call next value for hibernate_sequence |
05 | Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) |
06 | Hibernate: insert into Contact_Note (CONTACT_ID, message, id ) values (?, ?, ?) |
07 | Hibernate: select contact0_.ID as ID1_0_, contact0_.Email as Email2_0_, contact0_.First_Name as First_Na3_0_, contact0_.Last_Name as Last_Nam4_0_, contact0_.Phone_Number as Phone_Nu5_0_, contact0_.Phone_Type as Phone_Ty6_0_ from CONTACT contact0_ |
08 | Hibernate: delete from Contact_Note where id =? |
09 | Hibernate: delete from CONTACT where ID=? |
10 | Hibernate: select contact0_.ID as ID1_0_, contact0_.Email as Email2_0_, contact0_.First_Name as First_Na3_0_, contact0_.Last_Name as Last_Nam4_0_, contact0_.Phone_Number as Phone_Nu5_0_, contact0_.Phone_Type as Phone_Ty6_0_ from CONTACT contact0_ |
11 | 2018-03-08 19:25:54.778 INFO 13708 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_delete_the_contact_after_save_it@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]. |
12 | 2018-03-08 19:25:54.783 INFO 13708 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7671cb68: startup date [Thu Mar 08 19:25:50 CST 2018]; root of context hierarchy |
13 | 2018-03-08 19:25:54.785 INFO 13708 --- [ Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' |
- Line 8-9: two Delete statements
6.4 Find
it_can_find_contacts_by_name_and_type output
01 | 2018-03-08 19:26:42.878 INFO 13712 --- [ main] j.z.d.j.r.ContactRepositoryTest : Started ContactRepositoryTest in 4.246 seconds (JVM running for 5.266) |
02 | 2018-03-08 19:26:42.949 INFO 13712 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_find_contacts_by_name_and_type@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@3c5dbdf8]; rollback [ true ] |
03 | Hibernate: call next value for hibernate_sequence |
04 | Hibernate: call next value for hibernate_sequence |
05 | Hibernate: call next value for hibernate_sequence |
06 | Hibernate: call next value for hibernate_sequence |
07 | Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) |
08 | Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) |
09 | Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) |
10 | Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) |
11 | Hibernate: select contact0_.ID as ID1_0_, contact0_.Email as Email2_0_, contact0_.First_Name as First_Na3_0_, contact0_.Last_Name as Last_Nam4_0_, contact0_.Phone_Number as Phone_Nu5_0_, contact0_.Phone_Type as Phone_Ty6_0_ from CONTACT contact0_ where contact0_.Phone_Type=? and contact0_.Last_Name=? |
12 | 2018-03-08 19:26:43.098 INFO 13712 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test context [DefaultTestContext@2ea6137 testClass = ContactRepositoryTest, testInstance = jcg.zheng.demo.jpademo.repository.ContactRepositoryTest@400cff1a, testMethod = it_can_find_contacts_by_name_and_type@ContactRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41ee392b testClass = ContactRepositoryTest, locations = '{}' , classes = '{class jcg.zheng.demo.jpademo.JpaDemoApplication}' , contextInitializerClasses = '[]' , activeProfiles = '{}' , propertySourceLocations = '{}' , propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}' , contextCustomizers = set [[ImportsContextCustomizer@1e67a849 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot. test .autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot. test .autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot. test .context.filter.ExcludeFilterContextCustomizer@1f554b06, org.springframework.boot. test .json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@131276c2, org.springframework.boot. test .mock.mockito.MockitoContextCustomizer@0, org.springframework.boot. test .autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d95d2a2, org.springframework.boot. test .autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot. test .autoconfigure.properties.PropertyMappingContextCustomizer@d7556ade, org.springframework.boot. test .autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@528931cf], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader' , parent = [null]]]. |
13 | 2018-03-08 19:26:43.103 INFO 13712 --- [ Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7671cb68: startup date [Thu Mar 08 19:26:39 CST 2018]; root of context hierarchy |
14 | 2018-03-08 19:26:43.105 INFO 13712 --- [ Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' |
- Line 11: Select statements
7. Summary
In this example, we built a Spring Boot project to demonstrate how easy it is to configure and use Spring data JpaRepository
to manage the data in the database.
Spring Data JPA provides an abstraction to the persistence layer and has a common API. All you have to do is to implement a Repository
interface, declare the repository methods and annotate the methods with @Query
that should be executed.
However, There are some pitfalls when using JPA. Please check here for detail.
8. Download the Source Code
This example consists of a Spring Boot JPA project.