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();
}
SpringBoot使用JPA来做数据查询的更多相关文章
- springboot使用validation 插件做数据校验
不多说废话. 首先,我们需要在入参实体对象中,使用注解,控制 @Datapublic class UpdateShufflingRequest { private String shuffling_l ...
- SpringBoot中JPA使用动态SQL查询
https://www.jianshu.com/p/f72d82e90948 可以重点关注方法二,把原生sql传入数据库去查询 好处是:更加灵活坏处是:拼接sql比较痛苦,也容易出问题,比如拼接的sq ...
- 工作流activiti-03数据查询(流程定义 流程实例 代办任务) 以及个人小练习
在做数据查询的时候通过调用api来查询数据是相当的简单 对分页也进行了封装listPage(0, 4) ;listPage:分页查询 0:表示起始位置,4:表示查询长度 但是公司的框架封装了分页数据 ...
- 第11章—使用对象关系映射持久化数据—SpringBoot+SpringData+Jpa进行查询修改数据库
SpringBoot+SpringData+Jpa进行查询修改数据库 JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分.但它又不限于EJB 3.0,你可以在Web应用.甚至桌面应用 ...
- springboot集成Spring Data JPA数据查询
1.JPA介绍 JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.它的出现主要是为 ...
- SpringBoot Data JPA 关联表查询的方法
SpringBoot Data JPA实现 一对多.多对一关联表查询 开发环境 IDEA 2017.1 Java1.8 SpringBoot 2.0 MySQL 5.X 功能需求 通过关联关系查询商店 ...
- SpringBoot数据访问(二) SpringBoot整合JPA
JPA简介 Spring Data JPA是Spring Data大家族的一部分,它可以轻松实现基于JPA的存储库.该模块用于增强支持基于JPA的数据访问层,它使我们可以更加容易地构建使用数据访问技术 ...
- ajax基础语法、ajax做登录、ajax做用户名验证是否可用、ajax做关键字查询动态显示、ajax做用表格显示数据并增加操作列
AJAX: AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新. ...
- 带你搭一个SpringBoot+SpringData JPA的环境
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 不知道大家对SpringBoot和Spring Da ...
随机推荐
- python之pandas学习笔记-pandas数据结构
pandas数据结构 pandas处理3种数据结构,它们建立在numpy数组之上,所以运行速度很快: 1.系列(Series) 2.数据帧(DataFrame) 3.面板(Panel) 关系: 数据结 ...
- CSP考试策略
准备 带好手表,身份证,准考证,文具,和矿泉水(热水). 考试之前 如果时间比较充足,可以重启测试保护是否解开. 调整显示屏亮度,检查键盘.鼠标. 关掉拓展名隐藏. 写个简单程序测试是否有异常,测试对 ...
- 【Java开发】Maven那点事儿(Eclipse版)
Maven那点事儿(Eclipse版) 前言: 由于最近工作学习,总是能碰到Maven的源码.虽然平时工作并不使用Maven,但是为了学习一些源码,还是必须要了解下.这篇文章不是一个全面的Maven解 ...
- 微信小程序实现navbar导航栏
一.效果图 二.涉及到组件 1.view组件 2.swiper组件 三.原理 整体来讲是比较简单的,顶部的navbar是使用flex进行布局的:下面的内容区域则是使用到swiper组件,使用方式比较简 ...
- beam search 和 greedy search
贪心搜索(greedy search): 贪心搜索最为简单,直接选择每个输出的最大概率,直到出现终结符或最大句子长度. 集束搜索(beam search): 集束搜索可以认为是维特比算法的贪心形式,在 ...
- 消息中间件RabbitMq的代码使用案例
消费者: ---------------------- 构造初始化: public RabbitMqReceiver(String host, int port, String username, S ...
- 人渣给我笔记本网络适配器里加的的“bluetooth设备(个人局域网)”,卸载不掉
- JavaScript引用类型简单记录
Object Array instanceof Function 引用类型 - Object {} 等价于 new Object() 我们经常使⽤用对象来承载可选参数,⽽而⽤用 命名的形式参数来传递必 ...
- GIT SSH-KEY配置以及问题解决
GIT SSH-KEY 生成 我们在使用git的时候需要生成ssh key,我在这里说一下生成key和一些个性化操作,如:保存key的位置,如何解决Could not open a connectio ...
- Smarty内置函数之capture
capture的作用是: 捕获模板输出的数据并将其存储到一个变量,而不是把它们输出到页面,任何在 {capture name="foo"}和{/capture}之间的数据将被存储到 ...