SpringBoot Jpa複雑な動的sqlクエリを実現


SpringBoot Jpa複雑な動的sqlクエリを実現
ここではJpaを利用して複雑なダイナミックsqlクエリーを実現する方法についてお話しします.Jpaの紹介についてはあまり話しません.皆さんが知っていると信じています.はい、あまり言わないで、テーマに直行しましょう.
私のSpringBoot 2.3.1は、バージョンによって少し違いがあるかもしれませんが、大同小異です.少し修正すればいいです.
まず、エンティティクラス
@Data
@Entity
@Table(name = "master_user")    //    ,            
public class User {

    /**
     *   userId    ,              userId       user_id
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer userId;

    /**
     *            ,        mysql         
     */
    @Column(nullable = false, unique = true, columnDefinition = "varchar(32) COMMENT '   '")
    private String username;

    @Column(nullable = false, columnDefinition = "tinyint(4) COMMENT '   0  1 '")
    private Integer gender;

    @Column(nullable = false)
    private Integer age;

}

二直接照会を見る
ここでサービス実装層を直接貼り付け、Specificationを通じて動的クエリーを実装し、Root rootは実体クラスの具体的な属性を取得し、CriteriaBuilder cbはクエリー条件を接合し、クエリー条件を接合した後、CriteriaQuery queryを通じてクエリーを実装し、以下に示す.
	@Override
	public Page<User> findAllBySf(Integer gender, Integer age, String username, Integer pageNo, Integer pageSize) {
        //    
        Specification<User> sf = (Specification<User>) (root, query, cb) -> {
            //          
            List<Predicate> p = new ArrayList<>();
            if (null != gender) {
                Predicate p1 = cb.equal(root.get("gender").as(Integer.class), gender);
                p.add(p1);
            }
            if (null != age) {
                Predicate p2 = cb.greaterThan(root.get("age").as(Integer.class), age);
                p.add(p2);
            }
            if (!StringUtils.isEmpty(username)) {
                Predicate p3 = cb.like(root.get("username").as(String.class), "%" + username + "%");
                p.add(p3);
            }
            Predicate[] pre = new Predicate[p.size()];
            Predicate and = cb.and(p.toArray(pre));     //     and
            //Predicate or = cb.or(p.toArray(pre));       //     or
            query.where(and);       //      

            //    
            List<Order> orders = new ArrayList<>();
            orders.add(cb.desc(root.get("age")));       //  
            orders.add(cb.asc(root.get("username")));   //  
            return query.orderBy(orders).getRestriction();
        };
        Pageable pageable = PageRequest.of(pageNo, pageSize);
        return userDao.findAll(sf, pageable);
    }

具体的な説明は、コード注釈で説明しましたが、見ればわかると信じています.JPAクエリーは確かに便利で、xmlファイルを省くことができ、データベーステーブルを自動的に生成することができ、非常に便利であることがわかります.
では、このSpecification ですか?dao層を見続けます
三ここはdao階です
ここにカスタムクエリーを追加しました.修正操作を実行する場合も簡単です.@Modifyingの注釈を追加すればいいです.ここではあまりプレゼンテーションをしません.
//BaseDao
@NoRepositoryBean//  dao,          jpa       bean  spring  
public interface BaseDao<T, V> extends JpaRepository<T, V>, JpaSpecificationExecutor<T> {
}


@Repository("masterUserDao") //        UserDao,         masterUserDao
public interface UserDao extends BaseDao<User, Integer> {

	//       ,     
    User findOneByUsernameAndAge(String username, Integer age);
    
    //?1                   
    @Query("select u from User u where u.gender = ?1 and u.age = ?2 and u.username like %?3%")
    List<User> query(Integer gender, Integer age, String username);

    //query2() query()          query()        ,        
    @Query("select u from User u where u.gender = :gender and u.age = :age and u.username like %:username%")
    List<User> query2(@Param("gender") Integer gender,
                      @Param("age") Integer age,
                      @Param("username") String username);

    //query3() query()1 2     nativeQuery=true      sql
    @Query(value = "select * from master_user u where u.gender = ?1 and u.age = ?2 and u.username like %?3%", nativeQuery = true)
    List<User> query3(Integer gender, Integer age, String username);

}

具体的なテストは貼らないで、現地で測定したことがあって、すべてokです.ちなみに、daoレイヤのカスタム@Queryクエリはすべてパラメータを転送し、転送しないとnullとしてクエリされます.
はい、ここでは簡単な例ですが、他の多くの使い方は仲間たちが自分で掘り起こして、読んでくれてありがとう.