Springboot uses Spring Data JPA to implement database operation

  • 2021-10-13 07:39:32
  • OfStack

SpringBoot Integrates JPA

Using database is the foundation of developing basic applications, With the development framework, instead of writing the original code to access the database, or calling the underlying code such as JDBC (Java Data Base Connectivity) or connection pooling, we will access the database from a higher level, especially in Springboot. In this chapter, we will explain in detail how to use Spring Data JPA in Springboot to operate on the database.

JPA & Spring Data JPA

JPA is the abbreviation of Java Persistence API, and its Chinese name is Java persistence layer API, which is the Java persistence specification officially proposed by Sun.

Its main design goal is to simplify the existing persistence development work and integrate ORM technology.

JPA uses XML files or annotations (JDK 5.0 or later) to describe the mapping relationship between objects and associated tables, and can persist entity objects at runtime to databases. It provides ORM tools for Java developers to manage relational data in Java applications.

Simply put, JPA is a standard specification for persistence of POJO (Plain Ordinary Java Object), that is, ordinary objects of Java are persisted to the database through object relational mapping (Object-Relational Mapping, ORM).

Because JPA is developed on the basis of fully absorbing the existing Hibernate, TopLink, JDO and other ORM frameworks, it has the advantages of easy use and strong scalability.

Spring Data JPA is a framework developed by Spring based on Spring Data and JPA specification. Using Spring Data JPA can greatly simplify the writing of JPA, and can access and operate database almost without writing. Besides CRUD, it also includes some common functions such as paging and sorting.

Spring Data JPA also provides support for paging query, user-defined SQL, query specified N records, join table query and other functions

JPA is not a new ORM framework. It is only used to standardize the existing ORM technology, and it cannot replace the existing Hibernate, TopLink and other frameworks. On the contrary, we will still use these ORM frameworks when developing with JPA, but the applications developed at this time no longer depend on a persistence provider. The application can run in any JPA environment without modifying the code, and truly achieve low coupling and extensible programming.

Hibernate & JPA

1. JPA

The full name is Java Persistence API, which describes the mapping relationship between objects and relational tables through JDK 5.0 annotations or XML, and persists the entity objects at runtime to the database.

JPA appeared for two reasons:

1, simplifying the development work of object persistence of existing Java EE and Java SE applications;

2. Sun hopes to integrate the technology of ORM and realize the unification of persistence field.

Technologies provided by JPA:

1) ORM mapping metadata: JPA supports XML and JDK 5.0 annotation two metadata forms, metadata describes the mapping relationship between objects and tables, and the framework persists entity objects to database tables according to this;

2) API of JPA: Used to operate entity objects and execute CRUD operations, the framework completes all things for us in the background, and developers are freed from tedious JDBC and SQL codes.

3) Query language: Query data through object-oriented rather than database-oriented query language, avoiding the tight coupling of SQL statements of the program.

2. JPA & Hibernate relationship

JPA is the specification, Hibernate is the framework, JPA is the persistence specification, and Hibernate implements JPA.

Hibernate VS Mybatis

Mybatis: Small, convenient, efficient, simple, direct, semi-automatic

Hibernate: Powerful, convenient, efficient, complex, rounded, fully automatic

1. Import dependencies


<dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2. Simple CRUD

1. Configuration file


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      # Define the generation strategy of database tables  create  Create 1 Table  update  Update or create a data table 
      ddl-auto: update
      # Console display sql Statement 
    show-sql: true
server:
  port: 80

Among them, spring. jpa. hibernate. ddl-auto parameters are used to configure whether to turn on automatic updating of database table structure, and five values, create, create-drop, update, validate and none, can be taken.

When create loads hibernate, it first deletes the existing database table structure and then regenerates it; create-drop When hibernate is loaded, the existing database table structure is deleted first and then regenerated, and the generated database table structure is automatically deleted when sessionFactory is closed; update only automatically generates the database table structure when hibernate is loaded for the first time, and automatically updates the table structure according to model class when hibernate is loaded again later; validate Each time hibernate is loaded, the database table structure is validated, only the tables in the database are compared, no new tables are created, but new values are inserted. none Turn off automatic updates

2. Entity classes

Shop:


package com.shy.entity;
import lombok.Data;
import javax.persistence.*;
@Data
// Use jpa Annotation   Configure mapping relationship 
@Entity// Tell jpa This is 1 Entity classes   And datasheet mapped classes 
public class Shop{
    @Id// Indicates that this is based on 1 Primary keys 
    @GeneratedValue(strategy = GenerationType.IDENTITY)// Self-increasing 
    private Integer shopId;

    @Column(length = 20)
    private String shopName;

    private double price;

    private Integer shopClassId;

    private Integer num;
}

ShopClass, Product Category


package com.shy.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Data
@Entity
public class ShopClass {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer shopClassId;

    private String shopClassName;
}

3. Dao layer

Write dao to inherit the JpaRepository class, generics pass in the entity class to operate on, and primary key types


package com.example.dao;
import com.shy.entity.Shop;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/*  Parameter 1 T : Entities currently to be mapped 
 *  Parameter 2 ID : Object in the currently mapped entity OID( Mapping object identifier, database primary key ) Type of */

@Repository
public interface ShopRepository extends JpaRepository<Shop,Integer> {
    /*
     *  We inherit directly here  JpaRepository
     *  There are already many ready-made methods 
     *  This is also JPA Adj. 1 Great advantage 
     *  We can use these methods directly, including many methods of its parent class. 
     * */
}

JpaRepository:


package org.springframework.data.jpa.repository;

import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	@Override
	List<T> findAll();//  Query all entities 

	@Override
	List<T> findAll(Sort sort);//  Query all entities and sort them 

	@Override
	List<T> findAllById(Iterable<ID> ids);//  According to ID Collective query entity 

	@Override
	<S extends T> List<S> saveAll(Iterable<S> entities);//  Save and return the (modified) entity collection 

	void flush();//  Commit transaction 

	<S extends T> S saveAndFlush(S entity); //  Save the entity and commit the transaction immediately 

	<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

	@Deprecated
	default void deleteInBatch(Iterable<T> entities){deleteAllInBatch(entities);}

	void deleteAllInBatch(Iterable<T> entities); //  Bulk Delete Entity Collection 

	void deleteAllByIdInBatch(Iterable<ID> ids);

	void deleteAllInBatch();//  Bulk Delete All Entities 

	@Deprecated
	T getOne(ID id);//  According to ID Query entity 

	T getById(ID id);

	@Override
	<S extends T> List<S> findAll(Example<S> example);//  Query and Specification Example All Matching Entities 

	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);//  Query and Specification Example Matches all entities and sorts them 
}

4. service layer

service:


package com.shy.service;

import com.shy.entity.Shop;
import com.shy.vo.ShopAndShopClassVo;

import java.util.List;

public interface ShopService {
    // Inquire about all goods 
    List<Shop> findAll();

    // Increase merchandise 
    Shop addShop(Shop shop);

    // Through merchandise id Modify trade name 
    Shop updateShop();

    // Through merchandise id Delete merchandise 
    void delShop(Integer id);
}

Impl:


package com.shy.service;

import com.shy.dao.ShopRepository;
import com.shy.entity.Shop;
import com.shy.vo.ShopAndShopClassVo;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ShopServiceImpl implements ShopService{
    @Autowired
    private ShopRepository shopRepository;

    @Override
    public List<Shop> findAll() {
        return shopRepository.findAll();
    }

    @Override
    public Shop addShop(Shop shop) {
        shop.setPrice(333);
        shop.setShopClassId(3);
        shop.setNum(30);
        shop.setShopName(" Earphone ");
        return shopRepository.save(shop);
    }

    @Override
    public Shop updateShop() {
        Shop shop = new Shop();
        shop.setShopId(11);
        shop.setShopName(" Flat plate ");
        shop.setShopClassId(3);
        shop.setNum(40);
        return shopRepository.save(shop);
    }

    @Override
    public void delShop(Integer id) {
        shopRepository.deleteById(id);
        System.out.println(" Delete succeeded ");
    }
}

5. controller


package com.shy.controller;

import com.alibaba.fastjson.JSON;
import com.shy.entity.Shop;
import com.shy.service.ShopService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ShopController {
    @Autowired
    private ShopService shopService;

    @GetMapping("/list")
    public String findAll(){
        return JSON.toJSONString(shopService.findAll());
    }

    @GetMapping("/save")
    public String save(Shop shop){
        return JSON.toJSONString(shopService.addShop(shop));
    }

    @GetMapping("/saveAndFlush")
    public String saveAndFlush(){
        return JSON.toJSONString(shopService.updateShop());
    }

    @GetMapping("/delShop/{id}")
    public void delShop(@PathVariable Integer id){
        shopService.delShop(id);
    }

}

The whole process was tested with postman

3. Customize SQL

Add in ShopRepository


// Use native sql Need to add, nativeQuery = true
 	//?1 On behalf of 1 Parameters 
    @Query(value="select * from shop where shop.price = ?1",nativeQuery = true)
    Shop findByPrice(Double price);

    // Modify merchandise ,@Modifying+@Query Perform an update operation, serviceImpl Don't forget to add , To use the hql If you want to put entity Alias deletion 
    @Transactional// Designing an operation to modify a table requires transaction support to be turned on 
    @Modifying// This annotation only supports the return value of int/Integer
    @Query("update Shop s set s.shopName = ?1 where s.shopId = ?2")
    int updateshop2(String name,Integer shopId);

service:


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      # Define the generation strategy of database tables  create  Create 1 Table  update  Update or create a data table 
      ddl-auto: update
      # Console display sql Statement 
    show-sql: true
server:
  port: 80
0

Impl:


@Override
    public Shop findByPrice(Double price) {
        return shopRepository.findByPrice(price);
    }

	@Override
    public int updateshop2(String name, Integer shopId) {
        return shopRepository.updateshop2(name, shopId);
    }

controller:


@GetMapping("/listPrice/{price}")
    public String findByPrice(@PathVariable Double price){
        return JSON.toJSONString(shopService.findByPrice(price));
    }

	@GetMapping("/saveAndFlush2/{id}/{name}")
    public String saveAndFlush2(@PathVariable(value = "id") Integer shopId,
                               @PathVariable String name){
        return shopService.updateshop2(name, shopId)>0?" Successful modification ":" Modification failed ";
    }

4. Paging queries

Pageable is Spring encapsulated paging implementation class, the use of the need to pass in the number of pages, the number of pages and collation.

Spring Data JPA has built-in paging function for us. In the query method, the parameter Pageable needs to be passed in. When there are multiple parameters in the query, Pageable is recommended to be passed in as the last parameter.

When Pageable is used, the number of pages passed in, the number of pages per page and collation rules are required, and collation rules can be omitted

service:


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      # Define the generation strategy of database tables  create  Create 1 Table  update  Update or create a data table 
      ddl-auto: update
      # Console display sql Statement 
    show-sql: true
server:
  port: 80
3

Impl:


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      # Define the generation strategy of database tables  create  Create 1 Table  update  Update or create a data table 
      ddl-auto: update
      # Console display sql Statement 
    show-sql: true
server:
  port: 80
4

controller:


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      # Define the generation strategy of database tables  create  Create 1 Table  update  Update or create a data table 
      ddl-auto: update
      # Console display sql Statement 
    show-sql: true
server:
  port: 80
5

5. Linked table query

VO (value object) Value Object

Usually used for data transfer between business tiers, only containing data View object: View Object

Accept the object passed by the page and encapsulate the object

Encapsulate the objects completed by business processing into the data to be used by the page

Create an ShopAndShopClassVo to receive the results of a linked table query

entity, where the parametric construction must be added and assigned to it


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      # Define the generation strategy of database tables  create  Create 1 Table  update  Update or create a data table 
      ddl-auto: update
      # Console display sql Statement 
    show-sql: true
server:
  port: 80
6

ShopRepository:


// Connected table query 
    @Query("select new com.shy.vo.ShopAndShopClassVo(s.shopName,s.price,sc.shopClassName) from Shop 			s,ShopClass sc " +
            "where s.shopClassId=sc.shopClassId and sc.shopClassName=?1")
    List<ShopAndShopClassVo> findShopInfo(String shopClassName);

JPQL is similar to the native SQL statement, which is completely object-oriented and accessed by class name and attribute instead of table name and table attribute

service:


// Connected table query 
    List<ShopAndShopClassVo> findShopInfo(String shopClassName);

Impl:


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      # Define the generation strategy of database tables  create  Create 1 Table  update  Update or create a data table 
      ddl-auto: update
      # Console display sql Statement 
    show-sql: true
server:
  port: 80
9

controller:


@GetMapping("/andFind/{name}")
    public String findShopInfo(@PathVariable("name") String shopClassName){
        return JSON.toJSONString(shopService.findShopInfo(shopClassName));
    }

6. Query in groups

Another way to write the received data is to create a result set interface to receive the results after the query of the connected table

Defines an interface class for a result set. The content of the interface class comes from the commodity table and the commodity category table.

entity:


package com.shy.entity;

public interface GroupShop {
    String getNum();
    String getShopClassName();
}

In operation, Spring will automatically produce a proxy class for the interface (GroupShop) to receive the returned results, which is obtained in the form of getXX in the code.

ShopRepository:


// Group query 
    @Query("select count(s.shopName) as  Quantity of goods ,sc.shopClassName as  Category name  from Shop s,ShopClass sc where s.shopClassId=sc.shopClassId group by s.shopClassId")
    List<GroupShop> groupShop();

service:


// Group query 
    List<GroupShop> groupShop();

Impl:


@Override
    public List<GroupShop> groupShop() {
        return shopRepository.groupShop();
    }

controller:


@GetMapping("/groupShop")
    public String groupShop(){
        return JSON.toJSONString(shopService.groupShop());
    }

7. Comparison with mybatis

jpa is the mapping between objects, and mybatis is the mapping between objects and result sets jpa portability is better, do not care about what database, because mybatis free to write sql statements, so when the project transplant also need to change sql. JPA is simpler when modifying fields, and mybatis needs to modify 1 heap of xml, mapper and other files, which is very troublesome. mybatis user-defined sql, more flexible, can also write complex sql, JPA is only suitable for simple single table sql Summary: mybatis and JPA have their own advantages. If sql is simple, jpa is more efficient, and if sql is complex and needs to be customized, it is more convenient to use mybatis.

Related articles: