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();
}

  

SpringBoot使用JPA来做数据查询的更多相关文章

  1. springboot使用validation 插件做数据校验

    不多说废话. 首先,我们需要在入参实体对象中,使用注解,控制 @Datapublic class UpdateShufflingRequest { private String shuffling_l ...

  2. SpringBoot中JPA使用动态SQL查询

    https://www.jianshu.com/p/f72d82e90948 可以重点关注方法二,把原生sql传入数据库去查询 好处是:更加灵活坏处是:拼接sql比较痛苦,也容易出问题,比如拼接的sq ...

  3. 工作流activiti-03数据查询(流程定义 流程实例 代办任务) 以及个人小练习

    在做数据查询的时候通过调用api来查询数据是相当的简单 对分页也进行了封装listPage(0, 4) ;listPage:分页查询 0:表示起始位置,4:表示查询长度 但是公司的框架封装了分页数据  ...

  4. 第11章—使用对象关系映射持久化数据—SpringBoot+SpringData+Jpa进行查询修改数据库

    SpringBoot+SpringData+Jpa进行查询修改数据库 JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分.但它又不限于EJB 3.0,你可以在Web应用.甚至桌面应用 ...

  5. springboot集成Spring Data JPA数据查询

    1.JPA介绍 JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.它的出现主要是为 ...

  6. SpringBoot Data JPA 关联表查询的方法

    SpringBoot Data JPA实现 一对多.多对一关联表查询 开发环境 IDEA 2017.1 Java1.8 SpringBoot 2.0 MySQL 5.X 功能需求 通过关联关系查询商店 ...

  7. SpringBoot数据访问(二) SpringBoot整合JPA

    JPA简介 Spring Data JPA是Spring Data大家族的一部分,它可以轻松实现基于JPA的存储库.该模块用于增强支持基于JPA的数据访问层,它使我们可以更加容易地构建使用数据访问技术 ...

  8. ajax基础语法、ajax做登录、ajax做用户名验证是否可用、ajax做关键字查询动态显示、ajax做用表格显示数据并增加操作列

    AJAX: AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新.   ...

  9. 带你搭一个SpringBoot+SpringData JPA的环境

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 不知道大家对SpringBoot和Spring Da ...

随机推荐

  1. tf.metrics.sparse_average_precision_at_k 和 tf.metrics.precision_at_k的自己理解

    tensorflow最大的问题就是大家都讲算法,不讲解用法,API文档又全是英文的,看起来好吃力,理解又不到位.当然给数学博士看的话,就没问题的. 最近看了一系列非常不错的文章,做一下记录: http ...

  2. 【VS开发】RIbbon编程

    多彩界面,Ribbon编程 Ribbon是类似于office2007样式的界面,它替代了传统的MFC程序里的菜单和工具栏,MFC默认生成的Ribbon功能少,需要我们自己添加一些控件和图片等元素使界面 ...

  3. Android Service 入门

    说明 Service 工作在主进程上.生命周期图 两种状态 Started 比如Activity通过调用startService 方法.一旦被启动(Started),服务就永久在后台运行,即使创建他的 ...

  4. 查询list转化为tree的两种方式及排序

    方式一,数据库查询tree; MyBatis collection 集合 MyBatis 是数据持久层框架,支持定制化 SQL.存储过程以及高级映射.尤其强大在于它的映射语句,比如高级映射中的 col ...

  5. poco编译与运行

    1.引言 Poco C++库是: 一系列C++类库,类似Java类库,.Net框架,Apple的Cocoa; 侧重于互联网时代的网络应用程序 使用高效的,现代的标准ANSI/ISO C++,并基于ST ...

  6. [转帖]SSL延迟有多大?

    SSL延迟有多大? http://www.ruanyifeng.com/blog/2014/09/ssl-latency.html 转帖 作者: 阮一峰 日期: 2014年9月24日 感谢 腾讯课堂N ...

  7. PAT 甲级真题题解(121-155)

    1121 Damn Single 模拟 // 1121 Damn Single #include <map> #include <vector> #include <cs ...

  8. JVM 分析工具和查看命令,超详细

    jinfo 可以输出并修改运行时的java 进程的opts. jps 与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号. jstat 一个极强 ...

  9. laravel框架之自帶登錄&註冊

    //控制器層 <?php namespace App\Http\Controllers\admin; use App\Models\admin\Users; use Illuminate\Htt ...

  10. Codeforces 1238C. Standard Free2play

    传送门 题目别看错了,好像挺多人都读错了... 然后显然可以贪心,只有在需要用 $\text{magic crystals}$ 的时候才用 那么直接模拟即可 如果初始相邻两个突出的平台高度不连续那么我 ...