1. 程式人生 > >Spring-Data-JPA 爬坑記

Spring-Data-JPA 爬坑記

lse 失效 get 保存 con insert long 字段長度 CA

一: 實體類的常用註解

2.1 @Entity 標識這個 pojo 是一個 jpa 實體

2.2 @Table(name = "表名") 指定類對應的數據庫表名

2.3 @Id 標記某一字段為表主鍵

2.4 @GeneratedValue 標記主鍵生成策略

2.5 @Column 標記為字段,有如下屬性

2.5.1 name 對應數據庫的字段名,默認為 屬性名

2.5.2 unique 是否唯一,默認 false

2.5.3 nullable 是否可以為空 默認為 true

2.5.4 inserttable 是否可以插入,即提交 insert 語句時是否持久化的數據庫

2.5.5 updateable 是否可以跟新,即提交 update 語句時是否能修改該字段

2.5.6 length 字段長度

2.5.7 precision 和 scale 多少位數字,保留幾位小數

2.5.8 secondaryTable 從表名,該字段不在當前表,可以指定其它從表的名稱

2.5.9 columnDefinition 定義建表時創建此列的DDL,使用時,其它屬性將失效

2.5.9.1 columnDefinition="TEXT" 設置為文本類

2.6 @Temporal(TemporalType.DATE) 設置為時間類型

2.6.1 TemporalType.DATE yyyy-mm-dd

2.6.2 TemporalType.TIME hh:mm:ss

2.6.3 TemporalType.TIMESTAMP yyyy-mm-dd hh:mm:ss

二: 持久層 @Repository

1,Repository<T, T> 基礎接口, 第一個 T 實體類 第二個T 主鍵類型 如 <User, Long>

1.1 提供了以方法名為查詢條件方法

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

簡單的列子, 以上的 findBy 也可以改為 getBy 或者 readBy

package com.hwq.jpa.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Setter
@Getter
public class Status {

    @Id
    @GeneratedValue
    @JoinColumn
    Long id;

    Long pId;

    @Column(length = 20)
    String name;

}
package com.hwq.jpa.dao;

import com.hwq.jpa.entity.Status;
import org.springframework.data.repository.Repository;

@org.springframework.stereotype.Repository  // 註意兩個 Repository 不要沖突
public interface StatusDao extends Repository<Status, Long> {

    Status getById(Long id); // 根據 id Status 類

}

2, CrudRepository<T, T> 提供了簡單的增刪改查的方法, 繼承自 Repository<T, T>

3, PagingAndSortingRepository<T, T> 提供了分頁和排序的方法, 繼承自 CrudRepository<T, T>

4,JpaRepository<T, T> 繼承自 PagingAndSortingRepository<T, T>

5,JpaSpecificationExecutor<T> 條件查詢

簡單的例子,依然使用上面的實體類

package com.hwq.jpa.dao;

import com.hwq.jpa.entity.Status;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StatusDao extends JpaRepository<Status, Long>, JpaSpecificationExecutor<Status> {

}
package com.hwq.jpa.controller;

import com.hwq.jpa.dao.StatusDao;
import com.hwq.jpa.entity.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.*;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/status")
public class StatusController {

    @Autowired
    StatusDao statusDao;

    @RequestMapping("/insert")
    public Status insert(Status status) {
        // 保存或者修改的方法
        // 當存在主鍵時為修改,不存在為保存
        return statusDao.save(status);
    }

    @RequestMapping("select")
    public Map<String, Object> select(Integer page, Integer size) {
        // 實例化 排序類, Sort 可以傳入多個 Order
        // Direction.DESC 降序
        // Direction.ASC  升序
        // "id"           排序字段
        Order order1 = new Order(Direction.DESC, "id");
        Sort sort = new Sort(order1);

        // 實例化分頁類
        // page 查詢的當前頁數
        // size 查詢的每一頁的最大記錄數
        PageRequest pageAble = new PageRequest(page, size, sort);

        // 調用 findAll 方法
        Page<Status> result = statusDao.findAll(pageAble);

        // 獲取需要的數據
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rows", result.getTotalElements());    // 獲取總記錄數
        map.put("page", result.getNumber());           // 當前是第幾頁
        map.put("pages", result.getTotalPages());      // 總共多少頁
        map.put("data", result.getContent());          // 當前頁的數據
        map.put("size", result.getNumberOfElements()); // 當前頁的記錄數

        return map;
    }

    @RequestMapping("/select-if")
    public Map<String, Object> selectIf(Integer page, Integer size) {
        Order order1 = new Order(Direction.DESC, "id");
        Sort sort = new Sort(order1);
        PageRequest pageAble = new PageRequest(page, size, sort);
        Specification<Status> statusSpecification = new Specification<Status>() {
            @Override
            public Predicate toPredicate(Root<Status> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = null;  // 最終返回的對象, 由 cb 創建
                Path path = root.get("id");  // 定位到實體類的 id
                predicate = cb.gt(path, 1);  // WHERE id > 1
                return predicate;
            }
        };

        // 調用 findAll 方法
        Page<Status> result = statusDao.findAll(statusSpecification, pageAble);

        // 獲取需要的數據
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rows", result.getTotalElements());    // 獲取總記錄數
        map.put("page", result.getNumber());           // 當前是第幾頁
        map.put("pages", result.getTotalPages());      // 總共多少頁
        map.put("data", result.getContent());          // 當前頁的數據
        map.put("size", result.getNumberOfElements()); // 當前頁的記錄數

        return map;
    }

}

6,自定義的 Repository 方法《 註意以下三點 》《 無特殊情況,少用 》

6.1 必須創建一個任意的 接口 XxxDao

6.2 定義的 XxxRepository 繼承 XxxDao

6.3 實現 XxxDao 的類名稱必須為 XxxRepositoryImpl

6.3.1 實現類中可以使用 EntityManager 完美接入 JPA 的內容

簡單的例子, 依然使用最開始的實體類為

package com.hwq.jpa.repository.dao;

import com.hwq.jpa.entity.Status;

public interface StatusDao {
    Status selectStatusById(Long id);
}
package com.hwq.jpa.repository;

import com.hwq.jpa.entity.Status;
import com.hwq.jpa.repository.dao.StatusDao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface StatusRepository extends
        JpaRepository<Status, Long>, JpaSpecificationExecutor<Status>, StatusDao
{

}
package com.hwq.jpa.repository;

import com.hwq.jpa.entity.Status;
import com.hwq.jpa.repository.dao.StatusDao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class StatusRepositoryImpl implements StatusDao {

    @PersistenceContext
    EntityManager entityManager;

    @Override
    public Status selectStatusById(Long id) {
        Status status = entityManager.find(Status.class, id);
        return status;
    }
}

Spring-Data-JPA 爬坑記