SpringBoot使用JPA来做数据查询

Spring-Data-JPA在做数据存储方面真的很方便,它的目的就是写更少的代码,更多的事情,但是也有其力有未逮或者说处理起来比较闹心的地方。

  1.先来感受一下使用JPA做数据查询时,代码的简化程度

 
    
@CacheConfig(cacheNames = "news")
public interface NewsRepository extends PagingAndSortingRepository {
    @Cacheable
    NewsEntity findOne(Long id);

    @Cacheable
    NewsEntity findTop1ByOriginId(String originId);

    @Transactional
    long deleteByOriginId(String originId);           
    
    Page findDistinctByTitleStartingWithAndSimilarIdIsNullOrderByPubDateDesc(String title, Pageable pageable); 
}

单表查询时,只需要根据JPA提供的规范去命名,根本不需要自己去写什么查询语句就可以。

  2.当然要自己写SQL语句也没有问题

@Query(value = "select e.* from news_detail e INNER JOIN news_info n  on e.news_id = n.id where n.pub_date >= ?1", nativeQuery = true)
List listBypubDateWithEntityDetail(String pubDate);

@Query(value = "select n.id,GROUP_CONCAT(e.ent_id) from news_info n INNER JOIN map_news_company e on e.news_id = n.id where n.pub_date>= ?1 and n.id>?2 group by n.id order by n.id limit 10000", nativeQuery = true)
List listBypubDateWithEnts(String pubDate, long news_id); 
    
   

使用原生的SQL也可以,JPA就是这么方便,然而总有需要操心的地方——多条件分组查询。用过Hibernate和Mybatis的,在写业务逻辑的时候,拼接查询条件的时候,一定写过很多if条件不为空的判断,这就是JPA操蛋的地方。

  3.看看例子

    @Query(value = "select pub_time,count(1) as count from t_weibo where content like %:keyword% and pub_time>=:dateFrom and pub_time<=:dateTo group by pub_time", nativeQuery = true)
    List getWeibo(@Param("keyword") String keyword, @Param("dateFrom") Date dateFrom, @Param("dateTo") Date dateTo);

    @Query(value = "select pub_time,count(1) as count from t_weibo where content like %:keyword% and pub_time>=:dateFrom and pub_time<=:dateTo and region in ( select keyname from t_cell where  provincename=:provincename) group by pub_time", nativeQuery = true)
    List getWeiboByProvince(@Param("provincename") String provincename,@Param("keyword") String keyword,@Param("dateFrom") Date dateFrom, @Param("dateTo") Date dateTo);

这个例子两个方法的作用一样,条件个数不一样,这就是冗余了。

  4.如果是这样JPA被设计出来的意义是什么,jpa有一套来应对这些的措施,使用Specification这个来来完成条件拼接

User user1 = (User) userRepository.findOne(new Specification() {
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                /*criteriaQuery.where(criteriaBuilder.equal(root.get("name"), user.getName()),
                        criteriaBuilder.equal(root.get("password"), user.getPwd()));*/
          Predicate predicate = null;
          if(user.getName!=null&&!user.getName().equal){
            if(predicate!=null){
             predicate =
criteriaBuilder.equal(root.get("name"), user.getName())
                    }else{
              predicate =
criteriaBuilder.and(predicte,criteriaBuilder.equal(root.get("name"), user.getName()))
                    }
                }
          if(predicate!=null){
            criteriaQuery
.where(predicate);
          }
return null; } });

核心就是使用CriteriaBuilder 进行条件拼接

  5.还有一种方式就是使用QueryDsl插件来组合Spring Data JPA使用

添加maven依赖
        
        
            com.querydsl
            querydsl-jpa
            ${querydsl.version}
        
        
            com.querydsl
            querydsl-apt
            ${querydsl.version}
            provided
        
 配置querydsl插件
    
        
            
            
                com.mysema.maven
                apt-maven-plugin
                1.1.3
                
                    
                        
                            process
                        
                        
                            target/generated-sources/java
                            com.querydsl.apt.jpa.JPAAnnotationProcessor
                        
                    
                
            
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

此时编译(compile)一下maven项目,在这个(target/generated-sources/java)文件夹下看到对应于你建的实体类(User)的QueryDsl类(QUser)

@Entity
@Table(name = "users")
@Data
public class UserBean
{
    @Id
    @GeneratedValue
    @Column(name = "u_id")
    private Long id;
    @Column(name = "u_username")
    private String name;
    @Column(name = "u_age")
    private int age;
    @Column(name = "u_score")
    private double socre;
}

查询语句

@PersistenceContext
EntityManager entityManager;
@RequestMapping("query")
    public List list(){
        QUserBean userBean = QUserBean.userBean;
        JPAQuery jpaQuery = new JPAQuery<>(entityManager);
        return jpaQuery.select(userBean)
                .from(userBean)
                .where(userBean.name.eq("haha"))
                .fetch();
    }

  

转载于:https://www.cnblogs.com/shirandedan/p/8144769.html

你可能感兴趣的:(SpringBoot使用JPA来做数据查询)