Spring Data JPARepository Example
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.
You can also check this tutorial in the following video:
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
withJava
and Spring Boot version 1.5.10 and Add bothJPA
andH2
in the “search for dependencies” - Enter the group name as
jcg.zheng.demo
and artifact asjpademo
- 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 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <? xml version = "1.0" encoding = "UTF-8" ?> < project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" < modelVersion >4.0.0</ modelVersion > < groupId >jcg.zheng.demo</ groupId > < artifactId >spring-jparepository-demo</ artifactId > < version >0.0.1-SNAPSHOT</ version > < packaging >jar</ packaging > < name >spring-jparepository-demo</ name > < description >Demo Spring Data JPA Application</ description > < parent > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-parent</ artifactId > < version >1.5.10.RELEASE</ version > < relativePath /> <!-- lookup parent from repository --> </ parent > < properties > < project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding > < project.reporting.outputEncoding >UTF-8</ project.reporting.outputEncoding > < java.version >1.8</ java.version > </ properties > < dependencies > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-data-jpa</ artifactId > </ dependency > < dependency > < groupId >com.h2database</ groupId > < artifactId >h2</ artifactId > < scope >runtime</ scope > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > </ dependencies > < build > < plugins > < plugin > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-maven-plugin</ artifactId > </ plugin > </ plugins > </ build > </ project > |
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 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package jcg.zheng.demo.jpademo; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; @SpringBootApplication @EnableJpaRepositories (basePackages = "jcg.zheng.demo.jpademo" ) public class JpaDemoApplication { public static void main(String[] args) { SpringApplication.run(JpaDemoApplication. class , args); } @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build(); } @Bean public JpaVendorAdapter jpaVendorAdapter() { HibernateJpaVendorAdapter bean = new HibernateJpaVendorAdapter(); bean.setDatabase(Database.H2); bean.setGenerateDdl( true ); bean.setShowSql( true ); return bean; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) { LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean(); bean.setDataSource(dataSource); bean.setJpaVendorAdapter(jpaVendorAdapter); bean.setPackagesToScan( "jcg.zheng.demo.jpademo" ); return bean; } @Bean public JpaTransactionManager transactionManager(EntityManagerFactory emf) { 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 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | package jcg.zheng.demo.jpademo.entity; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import jcg.zheng.demo.jpademo.type.PhoneType; @Entity @Table (name = "CONTACT" ) public class Contact { @Id @GeneratedValue @Column (name = "ID" ) private Long id; @Column (name = "First_Name" ) private String firstName; @Column (name = "Last_Name" ) private String lastName; @Column (name = "Email" ) private String email; @Column (name = "Phone_Number" ) private String phoneNumber; @Column (name = "Phone_Type" ) @Enumerated (EnumType.STRING) private PhoneType phoneType; @OneToMany (mappedBy= "contact" , cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Contact_Note. class ) private List<Contact_Note> notes; public Contact() { } public Contact(String firstName, String lastName, String email, PhoneType phoneType, String phone) { this .firstName = firstName; this .lastName = lastName; this .email = email; this .phoneType = phoneType; this .phoneNumber = phone; } public Long getId() { return id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this .firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this .lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this .email = email; } public void setId(Long id) { this .id = id; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this .phoneNumber = phoneNumber; } public PhoneType getPhoneType() { return phoneType; } public void setPhoneType(PhoneType phoneType) { this .phoneType = phoneType; } public List<Contact_Note> getNotes() { if ( this .notes == null ) { this .notes = new ArrayList<>(); } return this .notes; } public void addNote(Contact_Note note){ getNotes().add(note); note.setContact( this ); } public void setNotes(List<Contact_Note> addresses) { 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 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package jcg.zheng.demo.jpademo.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @Entity public class Contact_Note { @Id @GeneratedValue private Long id; private String message; @ManyToOne @JoinColumn (name = "CONTACT_ID" ) private Contact contact; public Contact_Note() { super (); } public Long getId() { return id; } public void setId(Long id) { this .id = id; } public Contact getContact() { return contact; } public void setContact(Contact contact) { this .contact = contact; } public String getMessage() { return message; } public void setMessage(String message) { 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 2 3 4 5 | package jcg.zheng.demo.jpademo.type; public enum PhoneType { 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 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | package jcg.zheng.demo.jpademo.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import jcg.zheng.demo.jpademo.entity.Contact; import jcg.zheng.demo.jpademo.type.PhoneType; @Repository @Transactional public interface ContactRepository extends JpaRepository<Contact, Long> { @Query ( "SELECT con FROM Contact con WHERE con.phoneType=(:pType) AND con.lastName= (:lName)" ) List<Contact> 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 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 | package jcg.zheng.demo.jpademo.repository; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.junit4.SpringRunner; import jcg.zheng.demo.jpademo.entity.Contact; import jcg.zheng.demo.jpademo.entity.Contact_Note; import jcg.zheng.demo.jpademo.type.PhoneType; @RunWith (SpringRunner. class ) @DataJpaTest public class ContactRepositoryTest { @Autowired private ContactRepository contactRepo; @Test public void it_can_find_the_contact_after_save_it() { Contact contact = new Contact( "Mary" , "Zheng" , "test@test.com" , PhoneType.HOME, "6365272943" ); Contact_Note note = new Contact_Note(); note.setMessage( "She is a java geek" ); contact.addNote(note); contactRepo.save(contact); List contacts = contactRepo.findAll(); assertEquals( 1 , contacts.size()); assertEquals( "Mary" , contacts.get( 0 ).getFirstName()); assertEquals( "Zheng" , contacts.get( 0 ).getLastName()); assertEquals( "test@test.com" , contacts.get( 0 ).getEmail()); assertEquals(PhoneType.HOME, contacts.get( 0 ).getPhoneType()); assertEquals( "6365272943" , contacts.get( 0 ).getPhoneNumber()); assertEquals( 1 , contacts.get( 0 ).getNotes().size()); assertEquals( "She is a java geek" , contacts.get( 0 ).getNotes().get( 0 ).getMessage()); } @Test public void it_can_delete_the_contact_after_save_it() { Contact contact = new Contact( "Mary" , "Zheng" , "test@test.com" , PhoneType.HOME, "6365272943" ); Contact_Note note = new Contact_Note(); note.setMessage( "She is a java geek" ); contact.addNote(note); contactRepo.save(contact); List foundContacts = contactRepo.findAll(); contactRepo.delete(foundContacts.get( 0 )); List contacts = contactRepo.findAll(); assertEquals( 0 , contacts.size()); } @Test public void it_can_update_the_contact_after_save_it() { Contact contact = new Contact( "Mary" , "Zheng" , "test@test.com" , PhoneType.HOME, "6365272943" ); contactRepo.save(contact); contact.setEmail( "mary.zheng@test.com" ); contactRepo.save(contact); List contacts = contactRepo.findAll(); assertEquals( 1 , contacts.size()); assertEquals( "mary.zheng@test.com" , contacts.get( 0 ).getEmail()); } @Test public void it_can_find_contacts_by_name_and_type() { contactRepo.save( new Contact( "Mary" , "Zheng" , "mary.zheng@jcg.org" , PhoneType.HOME, "6368168164" )); contactRepo.save( new Contact( "Tom" , "Smith" , "tom.smith@jcg.org" , PhoneType.MOBILE, "(636) 527-2943" )); contactRepo.save( new Contact( "John" , "Joe" , "john.joe@jcg.org" , PhoneType.OFFICE, "(314) 527 2943" )); contactRepo.save( new Contact( "Cindy" , "Chang" , "cindy.change@jcg.org" , PhoneType.OTHER, "404-789-1456" )); List contactsWithZheng = contactRepo.findByLastNameAndPhoneType(PhoneType.HOME, "Zheng" ); assertEquals( 1 , contactsWithZheng.size()); Contact foundContact = contactsWithZheng.get( 0 ); assertEquals( "Mary" , foundContact.getFirstName()); assertEquals( "Zheng" , foundContact.getLastName()); assertEquals( "mary.zheng@jcg.org" , foundContact.getEmail()); assertEquals(PhoneType.HOME, foundContact.getPhoneType()); assertEquals( "6368168164" , foundContact.getPhoneNumber()); assertEquals( 0 , foundContact.getNotes().size()); } @Test public void it_return_null_when_not_found(){ Contact found = contactRepo.findOne(2L); assertNull(found); } } |
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 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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) 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 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 2018-03-08 19:21:55.544 INFO 5024 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version 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] 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' 2018-03-08 19:21:56.703 INFO 5024 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' 2018-03-08 19:21:56.724 INFO 5024 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ name: default ...] 2018-03-08 19:21:56.894 INFO 5024 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} 2018-03-08 19:21:56.898 INFO 5024 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found 2018-03-08 19:21:56.900 INFO 5024 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist 2018-03-08 19:21:56.985 INFO 5024 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} 2018-03-08 19:21:57.211 INFO 5024 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 2018-03-08 19:21:57.988 INFO 5024 --- [ main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update 2018-03-08 19:21:58.029 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT 2018-03-08 19:21:58.030 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT 2018-03-08 19:21:58.038 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note 2018-03-08 19:21:58.040 INFO 5024 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note 2018-03-08 19:21:58.121 INFO 5024 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2018-03-08 19:21:58.503 INFO 5024 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory 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) 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 ] Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) Hibernate: insert into Contact_Note (CONTACT_ID, message, id ) values (?, ?, ?) 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_ 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]]]. 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 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 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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) 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 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 2018-03-08 19:24:44.327 INFO 18416 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version 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] 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' 2018-03-08 19:24:45.520 INFO 18416 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' 2018-03-08 19:24:45.544 INFO 18416 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ name: default ...] 2018-03-08 19:24:45.698 INFO 18416 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} 2018-03-08 19:24:45.703 INFO 18416 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found 2018-03-08 19:24:45.705 INFO 18416 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist 2018-03-08 19:24:45.811 INFO 18416 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} 2018-03-08 19:24:46.051 INFO 18416 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 2018-03-08 19:24:46.834 INFO 18416 --- [ main] org.hibernate.tool.hbm2ddl.SchemaUpdate : HHH000228: Running hbm2ddl schema update 2018-03-08 19:24:46.868 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT 2018-03-08 19:24:46.869 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: CONTACT 2018-03-08 19:24:46.878 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note 2018-03-08 19:24:46.879 INFO 18416 --- [ main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: Contact_Note 2018-03-08 19:24:46.966 INFO 18416 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2018-03-08 19:24:47.286 INFO 18416 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory 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) 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 ] Hibernate: call next value for hibernate_sequence Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) Hibernate: update CONTACT set Email=?, First_Name=?, Last_Name=?, Phone_Number=?, Phone_Type=? where ID=? 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_ 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]]]. 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 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 02 03 04 05 06 07 08 09 10 11 12 13 | 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) 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 ] Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) Hibernate: insert into Contact_Note (CONTACT_ID, message, id ) values (?, ?, ?) 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_ Hibernate: delete from Contact_Note where id =? Hibernate: delete from CONTACT where ID=? 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_ 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]]]. 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 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 02 03 04 05 06 07 08 09 10 11 12 13 14 | 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) 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 ] Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) Hibernate: insert into CONTACT (Email, First_Name, Last_Name, Phone_Number, Phone_Type, ID) values (?, ?, ?, ?, ?, ?) 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=? 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]]]. 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 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. Spring Data JPARepository – 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.
You can download the full source code of this example here: Spring Data JpaRepository Example
In spring boot you don’t need to define: jpaVendorAdapter, entityManagerFactory,transactionManager
Just you need to have application.properties with this key values :
application.properties
# database configuration
spring.datasource.url=jdbc:h2:file:~/main-source;AUTO_SERVER=TRUE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
What will be table structure for both table ?