Chapter 02 Spring Data JPA
Section 01- Overview of Spring Data JPA
Spring Data JPA is a set of JPA application framework encapsulated by Spring based on ORM framework and JPA specification, which enables developers to access and operate databases with minimal code. It provides common functions including add, delete, change, check, etc., and easy to expand! Learning and using Spring Data JPA can greatly improve your development efficiency!
Spring Data JPA takes the DAO layer out of the way and basically all CRUDS can rely on it for implementation. In actual working projects, it is recommended to use Spring Data JPA + ORM (e.g. Hibernate), which provides great convenience when switching between DIFFERENT ORM frameworks, and also makes database layer operations simpler and easier to decouple
Spring Data JPA and the relationship between JPA and Hibernate
JPA is a set of specifications made up of interfaces and abstract classes. Hibernate is a mature ORM framework, and Hibernate implements THE JPA specification, so hibernate can also be called as an implementation of JPA. We use JPA API programming, which means that we look at the problem from a higher perspective (interface oriented programming).
Spring Data JPA is a more advanced encapsulation of JPA operations provided by Spring. It is a dedicated solution for Data persistence under the JPA specification.
Section 02-Spring Data JPA Best Practices
- Create a Maven project and add project dependencies
<properties>
<spring.version>5.2.6. RELEASE</spring.version>
<hibernate.version>5.0.7. The Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>8.0.19</mysql.version>
</properties>
<dependencies>
<! -- Junit Unit Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<! -- spring beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<! Spring support for the ORM framework
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<! -- spring end -->
<! -- hibernate beg -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1. The Final</version>
</dependency>
<! -- hibernate end -->
<! -- c3p0 beg -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<! -- c3p0 end -->
<! -- log end -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<! -- log end -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<! -- Spring data jPA coordinates -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.3.4
.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<! -- el beg using Spring data -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<! -- el end -->
</dependencies>
Copy the code
2. Create a configuration file and configure applicationContext. XML. All classes are managed by Spring
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<! Spring and Spring Data jPA configuration
<! -- Configure packet scanning -->
<context:component-scan base-package="com.citi" ></context:component-scan>
<! Create an entityManagerFactory object for the Spring container to manage.
<bean id="entityManagerFactoty" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<! -- Configure the scanned package (the package where the entity class is) -->
<property name="packagesToScan" value="com.citi.entity" />
<! -- JPA implementation manufacturer -->
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
<! -- JPA vendor adapter -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<! Create a database table automatically
<property name="generateDdl" value="false" />
<! -- Specify the database type -->
<property name="database" value="MYSQL" />
<! Database dialects: unique syntax supported -->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<! SQL > display SQL
<property name="showSql" value="true" />
</bean>
</property>
<! -- JPA dialect: Advanced features -->
<property name="jpaDialect" >
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<! Create database connection pool -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test? useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai" ></property>
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
</bean>
<! Spring dataJpa-->
<jpa:repositories base-package="com.citi.dao" transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactoty" ></jpa:repositories>
<! 4. Configure transaction manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoty"></property>
</bean>
<! -- 4.txAdvice-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<! -- 5.aop-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.citi.service.*.*(..) )" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
</aop:config>
</beans>
Copy the code
3. Create an entity class Customer in the Entity package and configure the mapping relationship between the entity class and the table, and between attributes and fields
@entity // indicates an Entity class @table (name = "Customer ") // Mapping indicates public class Customer {@id // declare primary key @GeneratedValue(strategy =) Generationtype.identity)// Declare primary key generation policy @column (name = "CUST_ID ") // Private Long custId; @Column(name = "cust_name") private String custName; @Column(name = "cust_source") private String custSource; @Column(name = "cust_level") private String custLevel; @Column(name = "cust_industry") private String custIndustry; @Column(name = "cust_phone") private String custPhone; @Column(name = "cust_address") private String custAddress; // omit the getter/setter/toString method}Copy the code
4. Create the CustomerDao interface class in the DAO layer and inherit JpaRepository and JpaSpecificationExecutor
/** * JpaRepository generic the first is the entity class of the operation, and the second is the primary key type */
public interface CustomerDao extends JpaRepository<Customer.Long>,JpaSpecificationExecutor<Customer> {}Copy the code
5. Create the CustomerDaoTest test class in the test package and create the testFindById method
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class CustomerDaoTest {
@Autowired
private CustomerDao customerDao;
/** * query by ID */
@Test
public void testFindById(a){
Customer customer = customerDao.findOne(2l); System.out.println(customer); }}Copy the code
Save () Saves or updates the operation
@Test
public void testSave(a){
// Save or update. If data exists, update it. If data does not exist, create it
Customer customer = new Customer();
customer.setCustName("Thor");
customer.setCustSource("Asgard");
customer.setCustLevel("VIP");
customer.setCustIndustry("God of Thunder");
customerDao.save(customer);
}
@Test
public void testUpdate(a){
// Save or update. If data exists, update it. If data does not exist, create it
Customer customer = customerDao.findOne(3l);
customer.setCustSource("INS");
customerDao.save(customer);
}
Copy the code
Delete () Delete operation
@Test
public void testDelete(a){
customerDao.delete(3l);
}
Copy the code
FindAll () queries all operations
@Test
public void testFindAll(a){
List<Customer> customerList = customerDao.findAll();
for(Customer customer : customerList) { System.out.println(customer); }}Copy the code
Implementation process
I: The instantiated customerDao is a dynamic proxy object SimpleJpaRepository
II:SimpleJpaRepository calls findOne(), and findOne() calls find() through the entity class manager EM to complete the query
Section 03- How to complete complex queries using Spring Data JPA
Query count()
@Test
public void testCount(a){
long count = customerDao.count();
System.out.println(count);
}
Copy the code
Does there exist ()
@Test
public void testExists(a){
boolean isExists = customerDao.exists(1l);
System.out.println(isExists);
}
Copy the code
Query getOne() by ID
@Test
@Transactional
public void testGetOne(a){
Customer one = customerDao.getOne(1l);
System.out.println(one);
}
Copy the code
The underlying call is getReference() of the EntityManager, loaded lazily, while find() is loaded immediately
Query methods in JPA:
Use JPQL for complex queries
JPQL: JPA Query Language
Features: The syntax or keywords are similar to SQL statements. It queries classes and properties within classes
The JPQL statement needs to be configured on the interface method
- Specific queries that require methods to be configured on the DAO interface
- Configure JPQL statements with annotations on the newly added methods
- Annotated as @ Query
New methods in the CustomerDao interface to query customers by customer name, using JPQL statements
@Query(value = "from Customer where custName= ?" )
Customer findByCustName(String custName);
Copy the code
Test the method in the CustomerDao
@Test
public void testFindByCustName(a){
Customer thor = customerDao.findByCustName("Thor");
System.out.println(thor);
}
Copy the code
The output
Multi-condition (multi-placeholder) queries
Add methods to the CustomerDao interface
// Query customers based on their names and ids
@Query(value = "from Customer where custName = ? and custId=?" )
Customer findByCustNameAndCustId(String custName, Long custId);
Copy the code
Test the method in CustomerDaoTest
@Test
public void testFindByCustNameAndCustId(a){
Customer thor = customerDao.findByCustNameAndCustId("Thor".3L);
System.out.println(thor);
}
Copy the code
Update custName with custId
The updateCustNameByCustId method is added to the CustomerDao interface
// Specify the position of the argument
// Declare an update operation
@Query(value = "update Customer set custName = ? 2 where custId = ? 1)"
@Modifying
@Transactional
void updateCustNameByCustId(Long custId, String custName);
Copy the code
Test the method in CustomerDaoTest
@Test
public void testUpdateCustName(a){
customerDao.updateCustNameByCustId(3L."Thor Odin");
}
Copy the code
Use SQL statements to complete complex queries
- Specific queries that require methods to be configured on the DAO interface
- On the newly added method, SQL query statements are configured in the form of annotations
- The annotation is @query (value=,nativeQuery=). Value indicates JPQL statement or SQL statement. NativeQuery indicates Boolean
SQL statement query all
Define method selectAll()
@Query(value = "SELECT * FROM customer", nativeQuery = true)
List<Customer> selectAll(a);
Copy the code
Test the method
@Test
public void testSelectAll(a){
List<Customer> customers = customerDao.selectAll();
for(Customer customer : customers) { System.out.println(customer); }}Copy the code
The output
SQL statement fuzzy query
Define the method selectByCustNameLike
@Query(value = "SELECT * FROM customer where cust_name like ? 1", nativeQuery = true)
List<Customer> selectByCustNameLike(String like);
Copy the code
Test the method
@Test
public void testSelectByCustNameLike(a){
List<Customer> customers = customerDao.selectByCustNameLike("Thor%");
for(Customer customer : customers) { System.out.println(customer); }}Copy the code
The output
Method name rule query
JPQL is a deeper layer of encapsulation for JPQL queries. You only need to define methods according to the method name rules provided by Spring Data JPA, and do not need to configure JPQL statements to complete the query
Naming rules: FindBy is used for the query. The attribute in the object is the query condition. For example, Customer is to be queried through custName. Select * from Customer where CUST_name =? By default, = is used. For fuzzy query, the keyword Like is used
findByCustName
Customer findByCustName(String custName);
Copy the code
@Test
public void testFindByCustName(a){
Customer thor = customerDao.findByCustName("Thor Odin");
System.out.println(thor);
}
Copy the code
The output
FindByCustNameLike fuzzy query
List<Customer> findByCustNameLike(String custName);
Copy the code
@Test
public void testFindByCustNameLike(a){
List<Customer> customers = customerDao.findByCustNameLike("Thor%");
for(Customer customer : customers) { System.out.println(customer); }}Copy the code
The output
The findByCustNameAndCustId multi-conditional query uses the And keyword, And the order of the attributes of the query should be the same as the order of the input parameters
Customer findByCustNameLikeAndCustIndustry(String custName, String custIndustry);
Copy the code
@Test
public void testFindByCustNameLikeAndCustIndustry(a){
Customer stark_industry = customerDao.findByCustNameLikeAndCustIndustry("Iron%"."Military Industry");
System.out.println(stark_industry);
}
Copy the code