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:

  1. 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.
  2. 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:

  1. spring-data-jpa
  2. Hibernate-core
  3. Hibernate–annotations
  4. 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?

  1. The Repository interface does not define methods.
  2. The CrudRepository interface, inherited from the Repository interface, defines basic add, delete, modify, and query functions.
  3. PagingAndSortingRepository interface, inherited from CrudRepository interface, defines the method of sorting and paging.
  4. 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