SpringBoot使用JPA來做數據查詢


Spring-Data-JPA在做數據存儲方面真的很方便,它的目的就是寫更少的代碼,更多的事情,但是也有其力有未逮或者說處理起來比較鬧心的地方。

  1.先來感受一下使用JPA做數據查詢時,代碼的簡化程度

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

    @Cacheable
    NewsEntity findTop1ByOriginId(String originId);

    @Transactional
    long deleteByOriginId(String originId);           
    
    Page<NewsEntity> 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<Object> 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<Object[]> 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<Object[]> 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<Object[]> 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<User>() {
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                /*criteriaQuery.where(criteriaBuilder.equal(root.<String>get("name"), user.getName()),
                        criteriaBuilder.equal(root.<String>get("password"), user.getPwd()));*/
          Predicate predicate = null;
          if(user.getName!=null&&!user.getName().equal){
            if(predicate!=null){
             predicate =
criteriaBuilder.equal(root.<String>get("name"), user.getName())
 }else{
              predicate =
criteriaBuilder.and(predicte,criteriaBuilder.equal(root.<String>get("name"), user.getName()))
 }
 }
          if(predicate!=null){
            criteriaQuery
.where(predicate);
          }
return null; } });

核心就是使用CriteriaBuilder 進行條件拼接

  5.還有一種方式就是使用QueryDsl插件來組合Spring Data JPA使用

添加maven依賴
        <!--queryDSL-->
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
            <version>${querydsl.version}</version>
        </dependency>
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <version>${querydsl.version}</version>
            <scope>provided</scope>
        </dependency>
 配置querydsl插件
    <build>
        <plugins>
            <!--該插件可以生成querysdl需要的查詢對象,執行mvn compile即可-->
            <plugin>
                <groupId>com.mysema.maven</groupId>
                <artifactId>apt-maven-plugin</artifactId>
                <version>1.1.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/generated-sources/java</outputDirectory>
                            <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

此時編譯(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<GoodEntity> list(){
        QUserBean userBean = QUserBean.userBean;
        JPAQuery<UserBean> jpaQuery = new JPAQuery<>(entityManager);
        return jpaQuery.select(userBean)
                .from(userBean)
                .where(userBean.name.eq("haha"))
                .fetch();
    }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM