preface
I have been using Mybatis as the persistence framework, and I think Mybatis is very good and flexible. Although I need to write SQL by myself, it is also an advantage of me, intuitive and convenient optimization.
But I think the JPA specification also has its advantages, such as simplicity and the complete absence of handwritten SQL for some basic CRUD operations.
So take advantage of the free time, do an understanding of Spring Data JPA, and simply write a Demo to learn to use.
define
There are several concepts that may be involved in this paper. Here are the definitions.
JPA
JPA, also known as Java Persistence API, is a Java Persistence interface proposed by Sun In the Java EE 5 specification, which is a specification.
ORM
Object Relational Mapping, or ORM for short. A programming technique used to convert data between systems of different types in object-oriented programming languages.
Hibernate
Hibernate is an ORM framework. Hibernate has been fully compliant with the JPA standard since version 3.2.
Mybatis
Mybatis is another ORM framework. Use it to build projects can see the Spring Boot Mybatis Web development environment setup
Spring Data JPA
Spring Data JPA is a JPA framework developed by Spring based on Hibernate, which implements THE JPA specification.
Spring Data JPA implementation principles
As mentioned earlier, one of the advantages of JPA is that you don’t have to write simple CRUD SQL statements, so how do you do that?
JPA can specify query statements in two ways:
- Spring Data JPA has access to JPA named queries. All you need to do is define a named query with a name that conforms to a given format, and Spring Data JPA uses the named query to implement its functionality when creating the proxy object.
- Developers can also use the @Query annotation directly on declared methods and provide a Query statement as a parameter, which Spring Data JPA uses to implement its functionality when creating proxy objects.
The first function is pretty much what you need in everyday life. You can use the @Query annotation to perform queries in your own SQL when you need to perform concatenated table queries or more complex operations.
The mapping between method names and SQL is in the appendix at the end of this article
Environment set up
First, use Spring Boot and Maven to build a project. This part will not be described here. If you are interested, you can follow the link above.
Add the dependent
Add the following dependencies to pox. XML, respectively:
- spring-data-jpa
- Hibernate-core
- Hibernate–annotations
- HikariCP
The fourth one is the connection pool I use, which is recommended by Spring Boot. Of course, you can change it to C3P0 or another connection pool.
<! -- spring-data-jpa -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.7. The Final</version>
</dependency>
<! -- https://mvnrepository.com/artifact/org.hibernate/hibernate-annotations -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.6 - Final</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency>
Copy the code
The configuration file
Add the following to the application.yaml file, setting up the service startup port, using the configuration to local and some of the data source configurations, and finally the JPA configuration.
server:
port: 9999
spring:
profiles:
active: local
datasource:
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 0
initial-size: 5
maximum-pool-size: 15
auto-commit: true
pool-name: NezhaHikariCP
test-connection-on-checkout: true
jpa:
database: MYSQL
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
Copy the code
At the same time, add the following content to create application-local.yaml to set the mysql data source information.
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: JDBC: mysql: / / 127.0.0.1 / test? characterEncoding=utf8&useSSL=false
username: root
password: root
jpa:
show-sql: true
Copy the code
Setting up the environment is as simple as above, the first step to add dependencies, the second step to add some configuration is OK.
All that’s left is to write some business code and no configuration classes at all!! No XML configuration either!!
The Demo to create
Create table
First, create a table in the database. This article tests the table (in the test database):
mysql> desc student; +------------+-------------+------+-----+---------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------------------+-----------------------------+ | id | int(10) | NO | | NULL | | | name | varchar(45) | NO | PRI | NULL | | | class_num | int(12) | YES | | NULL | | | age | int(3) | YES | | 18 | | | created_at | timestamp | NO | | CURRENT_TIMESTAMP | | | updated_at | timestamp | NO | | 2018-01-01 00:00:00 | on update CURRENT_TIMESTAMP | + -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- - + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + 6 rows in the set (0.01 SEC)Copy the code
Construction sentences are as follows:
CREATE TABLE `student` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'id'.`name` varchar(45) NOT NULL COMMENT 'name'.`class_num` int(12) DEFAULT NULL COMMENT 'class'.`age` int(3) DEFAULT '18' COMMENT 'age'.`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time'.`updated_at` timestamp NOT NULL DEFAULT '2018-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT 'Modification time',
PRIMARY KEY (`id`))ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
Copy the code
Creating an entity Class
Create Student entity class under model package:
package com.huyan.demo.model;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/** * created by huyanshi on 2018/12/21 */
@AllArgsConstructor
@Builder
@Data
@NoArgsConstructor
@Entity
@Table(name = "student")
public class Student {
@Id
private int id;
private String name;
private int classNum;
private int age;
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
@Temporal(TemporalType.TIMESTAMP)
private Date updatedAt;
}
Copy the code
Where, @entity identifies that this class is an Entity class, and @table specifies the associated data Table.
Create the DAO layer interface
package com.huyan.demo.dao;
import com.huyan.demo.model.Student;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/** * created by huyanshi on 2018/12/21 */
@Repository
public interface StudentDao extends JpaRepository<Student.String> {
List<Student> findAll(a);
}
Copy the code
Annotate the interface with @repository and implement the JpaRepository interface. This interface uses generics and needs to be provided with two types: the first is the type of the domain object handled by the interface, and the second is the primary key type of the domain object
Well, that’s the end of the demo, the service layer and controller layer, just call List
findAll(); This method looks up all the data in the table.
I wrote a very simple interface to return the list directly. The result set of the data is:
Note that there is no hand-written SQL in this process. If you are using Mybatis, you will need to write a select * from student SQL statement.
More method examples
It is hard to make JPA, of course, can not write a method to complete. This doesn’t help much in practice. So, I’ll test the usage of some common method types here and, finally, integrate them into the output.
The actual test I found that many methods have been defined in the inherited interface, such as query full, according to the primary key, add, delete, change, search, sorting, paging, etc., can be described as very powerful, so simple test greater than less than and multi-parameter query.
The following code actually runs through.
@Repository
public interface StudentDao extends JpaRepository<Student.Integer> {
// Query all
List<Student> findAll(a);
// The query age is greater than the incoming value
List<Student> findByAgeAfter(int age);
// query age and class equal to the input
List<Student> findByAgeAndClassNum(int age, int classNum);
// query the age of the students, and the results are sorted by the creation time
List<Student> findByAgeOrderByCreatedAt(int age);
// Update entity name, age and class based on primary key
@Modifying(clearAutomatically = true)
@Transactional
@Query(value = "UPDATE Student SET name = :name, classNum = :classNum, "
+ "age = :age WHERE id = :id ")
int updateNameAndAgeAndClassNumById(@Param("name") String name, @Param("age") int age,
@Param("classNum") int classNum, @Param("id") int id);
}
Copy the code
Which interface to inherit
In Spring Data JPA, there are four interfaces. Which one should we inherit?
- The Repository interface does not define methods.
- The CrudRepository interface, inherited from the Repository interface, defines basic add, delete, modify, and query functions.
- PagingAndSortingRepository interface, inherited from CrudRepository interface, defines the method of sorting and paging.
- JpaRepository interface, inherited from PagingAndSortingRepository interface, provides the flush (), saveAndFlush (), deleteInBatch () method.
But which interface to inherit? This is a matter of opinion, I use JPARepository as long as it doesn’t affect the business (the Crudrepository interface provides deletion methods, and sometimes you don’t want to).
The latter
After today’s study, I have a little understanding of Jpa. In my opinion, Jpa and Mysql are two different ideas, but they can both accomplish the same task.
When the business logic is relatively simple, using JPA can improve development efficiency because you don’t even need to write….. for basic add, delete, change and review And then you can do most of the simpler queries by defining method names, or if you have to, @Query handwritten SQL back-up.
Appendix: method keywords and usage and the generated SQL list
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ? 1 and x.firstname = ? 2 |
Or | findByLastnameOrFirstname | … where x.lastname = ? 1 or x.firstname = ? 2 |
Is,Equals | findByFirstnameIs,findByFirstnameEquals | … where x.firstname = ? 1 |
Between | findByStartDateBetween | … where x.startDate between ? 1 and ? 2 |
LessThan | findByAgeLessThan | … where x.age < ? 1 |
LessThanEqual | findByAgeLessThanEqual | … Where x.a ge ⇐? 1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ? 1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ? 1 |
After | findByStartDateAfter | … where x.startDate > ? 1 |
Before | findByStartDateBefore | … where x.startDate < ? 1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ? 1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ? 1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ? 1 (parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ? 1 (parameter bound with prepended %) |
Containing | findByFirstnameContaining | … where x.firstname like ? 1 (parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ? 1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ? 1 |
In | findByAgeIn(Collection<Age> ages)</Age> | … where x.age in ? 1 |
NotIn | findByAgeNotIn(Collection<Age> age)</Age> | … where x.age not in ? 1 |
TRUE | findByActiveTrue() | … where x.active = true |
FALSE | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(? 1) |
Refer to the link
www.ibm.com/developerwo… Segmentfault.com/a/119000000…
To the end.
ChangeLog
All the above are personal thoughts, if there is any mistake welcome to comment.
Welcome to reprint, please sign and keep the original link.
Contact email: [email protected]
For more study notes, see my personal blog ——>HuYan ten