1. 程式人生 > >springboot2.0 快速整合spring date jpa

springboot2.0 快速整合spring date jpa

這篇文章主要介紹如何使用spirng date jpa 稍帶腳的咱們在說說單元測試,學習新知識儘量先去看官方文件。在開說之前我們想宣告以springBoot 的版本 和spirng date jpa 的版本

springBoot:2.0.5.RELEASE

spring date jpa:2.0.10

jdk:1.8.0_144

下面就是檢視2.0.10 對應的官方文件來介紹我們的jpa

我是通過遊覽器的外掛進行翻譯的內容如下:

接下來我們進行版本文件閱讀

我們這裡不詳細介紹官方文件 只是 挑一些總要的進行介紹 。

1 搭建spirngboot jpa 基礎準備

1.1 引入spring data jpa 的start 依賴

首先我們先為我們先將spring date jpa 專案 依賴引入到springBoot 專案中

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

1.2 新增springBoot 資料來源的配置

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/learn
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
# Ddl-auto :  Create: 自動建立表 Update:自動修改表  Create-drop:應用停下來會把表刪除掉 None:什麼都不做  Validate:類和表明是否一致
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update

1.3 根據jpa 規範的註解配置對映實體

新增對映實體通過jpa 規範的註解 這裡我們不做過多解釋 喜歡刨底的同學請自行搜尋相關資料

package cn.lijunkui.springbootlearn.test.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private Integer age;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    private String sex;
    private String address;
    public  User(){

    }
    public User(Long id,String name,Integer age,String sex,String address){
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
        this.sex = sex;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

接下來正式進行spring date jpa 程式碼編寫部分,編寫之前我們先去檢視一下文件。

2 spring data jpa 內建查詢介面

2.1 CrudRepository 使用介紹

編寫dao  

package cn.lijunkui.springbootlearn.test.dao;

import cn.lijunkui.springbootlearn.test.model.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

public interface UserCrudRepository extends CrudRepository<User,Long>{

}

你肯定會驚訝 這就完成啦,我可以確定的告訴我們的Dao 開發完畢 基本可以完成我們基本的增刪改查。

檢視原始碼我們發現他有的方法是:

<S extends T> S save(S entity);//新增
<S extends T> Iterable<S> saveAll(Iterable<S> entities);//批量新增
Optional<T> findById(ID id);//查詢通過id
boolean existsById(ID id);//id是否存在
Iterable<T> findAll();//查詢所有
Iterable<T> findAllById(Iterable<ID> ids);//查詢多個id的資料
long count();//資料的總數
void deleteById(ID id);//根據id進行刪除
void delete(T entity);//根據例項進行刪除
void deleteAll(Iterable<? extends T> entities);//批量刪除
void deleteAll();//刪除所有

SpringBoot 的單元測試 需要我們宣告@SpringBootTest 和@RunWith 註解

我們這裡只是簡單寫啦幾個測試 因為這個方法確實沒有幾個方法

package cn.lijunkui.springbootlearn.test.dao;

import cn.lijunkui.springbootlearn.test.model.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;
import java.util.Optional;

import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserCrudRepositoryTest {
    @Autowired
    private UserCrudRepository userCrudRepository;

    /**
     *  新增使用者 測試
     */
    @Test
    public void add(){
        User user = new User();
        user.setName("ljk2");
        user.setSex("1");
        user.setAge(18);
        user.setAddress("beijing");
        User result = userCrudRepository.save(user);
        Assert.assertNotNull(result);
    }

    /**
     *  修改使用者
     */
    @Test
    public void edit(){
        User user = new User();
        user.setId(1l);
        user.setName("ljk2edit");
        user.setSex("1");
        user.setAge(18);
        user.setAddress("beijing");
        User result = userCrudRepository.save(user);
        Assert.assertNotNull(result);
    }

    /**
     * 通過id 進行查詢
     */
    @Test
    public void findById(){
        Optional<User> userOptional = userCrudRepository.findById(1l);
        User result = userOptional.get();
        Assert.assertNotNull(result);
    }

    /**
     *  查詢所有
     */
    @Test
    public void findAll(){
        List<User> userList = (List<User>)userCrudRepository.findAll();
        Assert.assertTrue(userList.size()>0);
    }
    @Test
    public void count(){
        long count = userCrudRepository.count();
        System.out.println(count);
    }

}

2.2 PagingAndSortRepository 使用介紹

根據文擋我們接著往下看 CrudRepository 只是具有增刪改查的一些基本功能 接下來 PagingAndSortingRepository 他是具有分頁和排序的功能 同時他繼承啦 CrudRepository

 

編寫測試用例:

package cn.lijunkui.springbootlearn.test.dao;

import cn.lijunkui.springbootlearn.test.model.User;
import org.hibernate.criterion.Order;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserPageRepositoryTest {

    @Autowired
    private UserPageRepository userPageRepository;

    @Test
    public void findAllBySort(){
        List<User> userList = (List<User>)userPageRepository.findAll(new Sort(Sort.Direction.ASC,"age"));
        System.out.println(userList.size());
    }
    @Test
    public void findAllByPageable(){

        Page<User> userPage =  userPageRepository.findAll(new PageRequest(0, 20));
        userPage.getNumber();//頁數
        userPage.getContent();//分頁的資料
        userPage.getTotalPages();//總共的頁數
        System.out.println("number:"+userPage.getNumber()
                +"Countet"+userPage.getContent().size()
                +"TotalPages"+userPage.getTotalPages());
    }
}

計數查詢

我們可以定義查詢每個欄位的個數

測試通過

計數刪除

執行test 報錯 說是我們需要事物 那我們就加上事物

deleteByName 也需要我們宣告事物的註解 才能夠刪除

2.3 JpaRepository 使用介紹

JpaRepository  不僅繼承啦 PagingAndSortingRepository 同時繼承啦 QueryByExampleExecutor(示例匹配器)

通過我們的測試用例查詢期詳細的用法

package cn.lijunkui.springbootlearn.test.dao;

import cn.lijunkui.springbootlearn.test.model.ResultDTO;
import cn.lijunkui.springbootlearn.test.model.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.*;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserJpaRepositoryTest {

    @Autowired
    private UserJpaRepository userJpaRepository;

    /**
     * 執行秒數:49422 49145
     * 批量儲存資料
     */
    @Test
    public void BatchSave(){
        long startTime = System.currentTimeMillis();
        List<User> list = new ArrayList<User>();
        for (int i = 0; i < 60000; i++) {
            User user = new User();
            user.setName("ljk"+i);
            user.setAge(i);
            user.setAddress("address"+i);
            list.add(user);
            if(i%100 == 0){
                userJpaRepository.saveAll(list);
                list.clear();
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("執行秒數:"+ (endTime - startTime));
    }
    /**
     * 執行秒數:48053 48394 執行速度比BatchSave 要快
     * 批量儲存資料 (高效處理方式)減少大事物的提交
     */
    @Test
    public void BatchSaveBest(){
        long startTime = System.currentTimeMillis();
        List<User> list = new ArrayList<User>();
        for (int i = 0; i < 60000; i++) {
            User user = new User();
            user.setName("ljk"+i);
            list.add(user);
            if(i%100 == 0){
                userJpaRepository.saveAll(list);
                userJpaRepository.flush();
                list.clear();
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("執行秒數:"+ (endTime - startTime));
    }
    /**
     * 查詢所有資料
     */
    @Test
    public void findALL(){
        List<User> userlists = userJpaRepository.findAll();
        Assert.assertTrue(userlists.size() > 0);
    }
    /**
     * 根據 age 排序查詢
     */
    @Test
    public void findALLSortAge(){
        List<User> lists = userJpaRepository.findAll(Sort.by(Sort.Direction.ASC ,"age"));
        for (User list : lists) {
            System.out.println(list);
        }
    }

    /**
     * 分頁查詢
     */
    @Test
    public void  findAllByPage(){
        PageRequest pageRequest = new PageRequest(0,1);
        Page<User> userPage = userJpaRepository.findAll(pageRequest);
        Assert.assertTrue(userPage.getContent().size() == 1);
    }

    /**
     *  分頁排序查詢
     */
    @Test
    public void findAllByPageAndSort(){
        PageRequest pageRequest = new PageRequest(0,3,Sort.by(Sort.Direction.ASC ,"age"));
        Page<User> userPage =  userJpaRepository.findAll(pageRequest);
        List<User> userList= userPage.getContent();
        for (User user : userList) {
            System.out.println(user);
        }
    }

    /**
     * 根據id 的集合獲取所有資料
     */
    @Test
    public void findAllByIds(){
        List<Long> ids = new ArrayList<Long>();
        ids.add(1l);
        ids.add(2l);
        ids.add(3l);
        ids.add(4l);
        List<User> userList = userJpaRepository.findAllById(ids);
        Assert.assertTrue(userList.size()>0);
    }



    /**
     * 批量刪除所有資料
     */
    @Test
    public void  deleteAllInBatch(){
        userJpaRepository.deleteAllInBatch();
    }

    /**
     *  儲存資料並重新整理快取
     */
    @Test
    public void saveAndFlush(){
        User user = new User();
        user.setName("ljk");
        user.setAge(18);
        user.setAddress("beijing");
        user.setSex("1");
        User result = userJpaRepository.saveAndFlush(user);
        Assert.assertNotNull(result);
    }

    /**
     * 批量刪除
     */
    @Test
    public void deleteInBatch(){
        List<User> userList = new ArrayList<User>();
        User user = new User();
        user.setId(1l);
        userList.add(user);
        User user2 = new User();
        user2.setId(2l);
        userList.add(user2);
        User user3 = new User();
        user3.setId(3l);
        userList.add(user3);
        User user4 = new User();
        user4.setId(4l);
        userList.add(user4);
        userJpaRepository.deleteInBatch(userList);
    }

    /**
     * 根據id 獲取資料 延遲載入
     */
    @Test
    public void getOne(){
        User result = userJpaRepository.getOne(1l);
        Long id = result.getId();
        String name = result.getName();
        System.out.println(id);
        System.out.println(name);
        Assert.assertNotNull(result);
    }

    /**
     * 示例匹配器 ExampleMatcher
     */
    @Test
    public void findUserByExam(){
        User user = new User();
        user.setName("ljk");
        List<User> list = userJpaRepository.findAll(Example.of(user));
        System.out.println(list.size());
    }
    @Test
    public void findUserByExamQuery(){
        User user = new User();
        user.setName("ljk");
        user.setAddress("address8");
        user.setAge(8);
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.startsWith())//模糊查詢匹配開頭,即{username}%
                .withMatcher("address" ,ExampleMatcher.GenericPropertyMatchers.contains())//全部模糊查詢,即%{address}%
                .withIgnorePaths("id");//忽略欄位,即不管id是什麼值都不加入查詢條件
        Example<User> example = Example.of(user ,matcher);
        List<User> userList = userJpaRepository.findAll(example);
        Assert.assertTrue(userList.size() > 0);
    }







}

3 方法名稱建立查詢

我們根據制定的規則編寫查詢方法 就像下圖所示 只需要定義個介面方法你就可以進行查詢你想要的資料

package cn.lijunkui.springbootlearn.test.dao;

import cn.lijunkui.springbootlearn.test.model.ResultDTO;
import cn.lijunkui.springbootlearn.test.model.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.*;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserJpaRepositoryTest {

    @Autowired
    private UserJpaRepository userJpaRepository;

    @Test
    public void findByNameAndAge(){
        List<User> userList = userJpaRepository.findByNameAndAge("ljk",18);
        Assert.assertTrue( userList.size()>0 );
    }

    public void findByNameOrAge(){
        List<User> userList = userJpaRepository.findByNameOrAge("ljk",18);
        Assert.assertTrue( userList.size()>0 );
    }
}

快速自定以查詢方法:示例如下

Table 3. Supported keywords inside method names
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

findByFirstname,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.age <= ?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)

… where x.age in ?1

NotIn

findByAgeNotIn(Collection<Age> ages)

… 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)

4 @Query註解查詢

package cn.lijunkui.springbootlearn.test.dao;

import cn.lijunkui.springbootlearn.test.model.ResultDTO;
import cn.lijunkui.springbootlearn.test.model.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
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 javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public interface UserJpaRepository extends JpaRepository<User,Long>{

    /**
     * 根據姓名查詢使用者
     * @param name
     * @return
     */
    @Query("select u from User u where u.name = ?1")
    public List<User> findUserByNameByQuery(String name);

    /**
     * 根據姓名(like)和年齡查詢使用者
     * @param name
     * @param age
     * @return
     */
    @Query("select u from User u where u.name like  CONCAT('%',?1,'%') and u.age = ?2" )
    public List<User> findUserByLikeNameByQuery(String name,Integer age);


    /**
     * 根據姓名(like)和年齡查詢使用者
     *  命名引數 進行查詢
     */
    @Query("select u from User u where u.name like CONCAT('%',:name,'%') and u.age = :age")
    public User findUserByNameAndAgeWithQery(@Param("name") String  name,@Param("age") Integer age);

    /**
     * 根據姓名(like)和年齡查詢使用者
     *  命名引數 原生方式進行查詢
     */
    @Query(value = "select * from user u where u.name like CONCAT('%',:name,'%') and u.age = :age",nativeQuery = true)
    public List<User> findUserByNameAndAgeWithQeryNative(@Param("name") String  name,@Param("age") Integer age);

    /**
     * 查詢每個地區的人的個數
     * @return
     */
    @Query("select new cn.lijunkui.springbootlearn.test.model.ResultDTO(u.address,count(u.id))  from User u group by u.address")
    public List<ResultDTO> findCountGroupByAddress();

}

測試用例:

package cn.lijunkui.springbootlearn.test.dao;

import cn.lijunkui.springbootlearn.test.model.ResultDTO;
import cn.lijunkui.springbootlearn.test.model.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.*;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserJpaRepositoryTest {

    @Autowired
    private UserJpaRepository userJpaRepository;

    @Test
    public void  findUserByNameByQuery(){
        List<User> userList = userJpaRepository.findUserByNameByQuery("ljk");
        Assert.assertNotNull(userList.size()>0);
    }
    @Test
    public void findUserByLikeNameByQuery(){
        List<User> userList = userJpaRepository.findUserByLikeNameByQuery("jk",18);
        Assert.assertNotNull(userList.size()>0);
    }
    @Test
    public void findUserByNameAndAgeWithQery(){
        User user = userJpaRepository.findUserByNameAndAgeWithQery("jk",18);
        Assert.assertNotNull(user);
    }
    @Test
    public void findUserByNameAndAgeWithQeryNative(){
        List<User> userList = userJpaRepository.findUserByNameAndAgeWithQeryNative("jk",18);
        Assert.assertNotNull(userList.size()>0);
    }
    /**
     * 零散引數的接收
     */
    @Test
    public void  findCountGroupByAddress(){
        List<ResultDTO> results  = userJpaRepository.findCountGroupByAddress();
        System.out.println(results);
    }

}