SpringData JPA整理

一 首先熟悉幾種jpa中的接口Repository,CrudRepository,PagingAndSortingRepository,JpaRepository,JpaSpecificationExecutor

Repository是一個空接口:java

@Indexed
public interface Repository<T, ID> {

}

  

CrudRepository繼承Repository:數據庫

@NoRepositoryBean
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {
    <S extends T> S save(S var1); //保存
    <S extends T> Iterable<S> save(Iterable<S> var1);//批量保存
    T findOne(ID var1);//根據id 查詢一個對象。返回對象自己,當對象不存在時,返回null
    boolean exists(ID var1)//根據id 判斷對象是否存在
    Iterable<T> findAll();;//查詢全部的對象
    Iterable<T> findAllById(Iterable<ID> var1);//根據id列表查詢全部的對象
    long count();//計算對象的總個數
    void delete(ID var1);//根據id 刪除
    void delete(T var1);//刪除一個對象
    void delete(Iterable<? extends T> var1);//批量刪除,集合對象(後臺執行時,一條一條刪除)
    void deleteAll();//刪除全部(後臺執行時,一條一條刪除)
}

  

PagingAndSortingRepository繼承CrudRepository,另提供了兩個方法,實現了分頁和排序的功能:緩存

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
    Iterable<T> findAll(Sort var1);// 僅排序
    Page<T> findAll(Pageable var1);// 分頁和排序
}

  

JpaRepository繼承PagingAndSortingRepository:app

@NoRepositoryBean
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    List<T> findAll(); //查詢全部對象,返回List
    List<T> findAll(Sort var1);//查詢全部對象,並排序,返回List
    List<T> findAll(Iterable<ID> var1);//根據id列表查詢全部的對象,返回List
    <S extends T> List<S> save(Iterable<S> var1);//批量保存,並返回對象List
    void flush();//強制緩存與數據庫同步
    <S extends T> S saveAndFlush(S var1);//保存並強制同步數據庫
    void deleteInBatch(Iterable<T> var1);//批量刪除集合對象(後臺執行時,生成一條語句執行,用多個or條件)
    void deleteAllInBatch();//刪除全部(執行一條語句,如:delete from user)
    T getOne(ID var1);//根據id 查詢一個對象,返回對象的引用(區別於findOne),當對象不存時,返回引用不是null,但各個屬性值是null
    <S extends T> List<S> findAll(Example<S> var1);//根據實例查詢
    <S extends T> List<S> findAll(Example<S> var1, Sort var2);//根據實例查詢,並排序
}

  

JpaSpecificationExecutor作動態SQL查詢L:less

/**
 * Interface to allow execution of {@link Specification}s based on the JPA criteria API.
 */
public interface JpaSpecificationExecutor<T> {
    T findOne(Specification<T> var1); //經過Specification查詢單個對象
    List<T> findAll(Specification<T> var1); //經過Specification查詢集合
    Page<T> findAll(Specification<T> var1, Pageable var2); //經過Specification分頁查詢
    List<T> findAll(Specification<T> var1, Sort var2); //經過Specification排序查詢
    long count(Specification<T> var1);//經過Specification統計
}

  

二 經常使用使用方式

1 用JpaRepository接口進行單表命名規範查詢:ide

Keyword
Sample
JPQL snippet

And測試

findByLastnameAndFirstnameui

… where x.lastname = ?1 and x.firstname = ?2code

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)

 

 

2 @Query自定義註解使用

public interface UserRepository extends JpaRepository<User, Long> {
  //這種"?1"佔位符要求和參數位置對應,推薦使用別名
  //nativeQuery=true說明爲原生SQL
  //@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
  @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = :emailAddress", nativeQuery = true)
  User findByEmailAddress(String emailAddress);
  
  //delete、update example
  @Modifying
  @Query("update User u set u.firstname = :firstname where u.lastname = :lastname")
  int setFixedFirstnameFor(String firstname, String lastname);
  
  @Modifying
  @Query("delete from User u where user.role.id = :roleId")
  void deleteInBulkByRoleId(long roleId);
}

  

3 利用JpaSpecificationExecutor實現動態SQL

Page<DemoUser> result = userRepository.findAll(
        new Specification<DemoUser>(){
            @Override
            public Predicate toPredicate(Root<DemoUser> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicates = new ArrayList<>();
 
                //關聯查詢 inner
                Join<DemoUser, DemoDept> join = root.join("demoDept", JoinType.INNER);
                //主表條件 like 動態條件
                if (StringUtils.isNotBlank(demoUserDtoQueryDto.getUserName())) {
                    predicates.add(builder.like(root.get("userName"), //屬性
                            "%" + demoUserDtoQueryDto.getUserName() + "%")); //值
                }
 
                //in使用測試
                CriteriaBuilder.In<Long> in = builder.in(root.get("id"));
                Arrays.asList(1L, 2L, 3L).forEach(e -> {
                    in.value(e);
                });
                predicates.add(in);
 
                //從表條件 id=1
                predicates.add(builder.equal(join.get("id"), 1)); //從表條件查詢 這裏測試
 
                //or使用 (password=4 or sex=1)
                predicates.add(builder.or(builder.equal(root.get("password"), "44"),
                        builder.equal(root.get("sex"), "1")));
 
                //對象類型比較要求比較器
                //<Y extends Comparable<? super Y>> Predicate greaterThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y);
                //   builder.greaterThanOrEqualTo();
                //   builder.lessThanOrEqualTo();
                //   builder.greaterThan();
                //   builder.lessThan();
                //直接用與數值類型的值進行比較
                //Predicate gt(Expression<? extends Number> x, Expression<? extends Number> y);
                //   builder.gt();
                //   builder.le();
                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
                //    query.where(predicates.toArray(new Predicate[predicates.size()]));
                //    return null;
            }
        },
        new PageRequest(page, pageSize); //分頁參數 還能夠添加排序字段
);


// ---------------------------------------------------------------------------------------
// Entity
@Entity
@Table(name = "demo_user")
@Data
public class DemoUser extends BaseDomain implements Serializable {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String userName;
    private String password;
    private Short sex;
 
    @ManyToOne
    @JoinColumn(name = "dept_id")
    @NotFound(action = NotFoundAction.IGNORE)
    private DemoDept demoDept;
 
}

// ---------------------------------------------------------------------------------------
// DAO
public interface UserRepository extends JpaRepository<DemoUser, Long>, JpaSpecificationExecutor<DemoUser> {}
相關文章
相關標籤/搜索