JPA 复杂查询 - Querydsl
添加依赖
<!--query dsl -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
</dependency>
<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>
运行 mvn compile, 将生成Query实体。
单表查询
package com.chhliu.springboot.jpa.repository; import java.util.List; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component; import com.chhliu.springboot.jpa.entity.QUser;
import com.chhliu.springboot.jpa.entity.User;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory; /**
* 描述:QueryDSL JPA
* @author chhliu
*/
@Component
@Transactional
public class UserRepositoryManagerDsl {
@Autowired
private UserRepositoryDls repository; @Autowired
@PersistenceContext
private EntityManager entityManager; private JPAQueryFactory queryFactory; @PostConstruct
public void init() {
queryFactory = new JPAQueryFactory(entityManager);
} public User findUserByUserName(final String userName){
/**
* 该例是使用spring data QueryDSL实现
*/
QUser quser = QUser.user;
Predicate predicate = quser.name.eq(userName);
return repository.findOne(predicate);
} /**
* attention:
* Details:查询user表中的所有记录
*/
public List<User> findAll(){
QUser quser = QUser.user;
return queryFactory.selectFrom(quser)
.fetch();
} /**
* Details:单条件查询
*/
public User findOneByUserName(final String userName){
QUser quser = QUser.user;
return queryFactory.selectFrom(quser)
.where(quser.name.eq(userName))
.fetchOne();
} /**
* Details:单表多条件查询
*/
public User findOneByUserNameAndAddress(final String userName, final String address){
QUser quser = QUser.user;
return queryFactory.select(quser)
.from(quser) // 上面两句代码等价与selectFrom
.where(quser.name.eq(userName).and(quser.address.eq(address)))// 这句代码等同于where(quser.name.eq(userName), quser.address.eq(address))
.fetchOne();
} /**
* Details:使用join查询
*/
public List<User> findUsersByJoin(){
QUser quser = QUser.user;
QUser userName = new QUser("name");
return queryFactory.selectFrom(quser)
.innerJoin(quser)
.on(quser.id.intValue().eq(userName.id.intValue()))
.fetch();
} /**
* Details:将查询结果排序
*/
public List<User> findUserAndOrder(){
QUser quser = QUser.user;
return queryFactory.selectFrom(quser)
.orderBy(quser.id.desc())
.fetch();
} /**
* Details:Group By使用
*/
public List<String> findUserByGroup(){
QUser quser = QUser.user;
return queryFactory.select(quser.name)
.from(quser)
.groupBy(quser.name)
.fetch();
} /**
* Details:删除用户
*/
public long deleteUser(String userName){
QUser quser = QUser.user;
return queryFactory.delete(quser).where(quser.name.eq(userName)).execute();
} /**
* Details:更新记录
*/
public long updateUser(final User u, final String userName){
QUser quser = QUser.user;
return queryFactory.update(quser).where(quser.name.eq(userName))
.set(quser.name, u.getName())
.set(quser.age, u.getAge())
.set(quser.address, u.getAddress())
.execute();
} /**
* Details:使用原生Query
*/
public User findOneUserByOriginalSql(final String userName){
QUser quser = QUser.user;
Query query = queryFactory.selectFrom(quser)
.where(quser.name.eq(userName)).createQuery();
return (User) query.getSingleResult();
} /**
* Details:分页查询单表
*/
public Page<User> findAllAndPager(final int offset, final int pageSize){
Predicate predicate = QUser.user.id.lt(10);
Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "id"));
PageRequest pr = new PageRequest(offset, pageSize, sort);
return repository.findAll(predicate, pr);
}
}
多表操作示例(一对一)
package com.chhliu.springboot.jpa.repository; import java.util.ArrayList;
import java.util.List; import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import com.chhliu.springboot.jpa.dto.PersonIDCardDto;
import com.chhliu.springboot.jpa.entity.QIDCard;
import com.chhliu.springboot.jpa.entity.QPerson;
import com.querydsl.core.QueryResults;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory; @Component
public class PersonAndIDCardManager {
@Autowired
@PersistenceContext
private EntityManager entityManager; private JPAQueryFactory queryFactory; @PostConstruct
public void init() {
queryFactory = new JPAQueryFactory(entityManager);
} /**
* Details:多表动态查询
*/
public List<Tuple> findAllPersonAndIdCard(){
Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
JPAQuery<Tuple> jpaQuery = queryFactory.select(QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name)
.from(QIDCard.iDCard, QPerson.person)
.where(predicate);
return jpaQuery.fetch();
} /**
* Details:将查询结果以DTO的方式输出
*/
public List<PersonIDCardDto> findByDTO(){
Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
JPAQuery<Tuple> jpaQuery = queryFactory.select(QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name)
.from(QIDCard.iDCard, QPerson.person)
.where(predicate);
List<Tuple> tuples = jpaQuery.fetch();
List<PersonIDCardDto> dtos = new ArrayList<PersonIDCardDto>();
if(null != tuples && !tuples.isEmpty()){
for(Tuple tuple:tuples){
String address = tuple.get(QPerson.person.address);
String name = tuple.get(QPerson.person.name);
String idCard = tuple.get(QIDCard.iDCard.idNo);
PersonIDCardDto dto = new PersonIDCardDto();
dto.setAddress(address);
dto.setIdNo(idCard);
dto.setName(name);
dtos.add(dto);
}
}
return dtos;
} /**
* Details:多表动态查询,并分页
*/
public QueryResults<Tuple> findByDtoAndPager(int offset, int pageSize){
Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
return queryFactory.select(QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name)
.from(QIDCard.iDCard, QPerson.person)
.where(predicate)
.offset(offset)
.limit(pageSize)
.fetchResults();
}
}
上面将查询结果以DTO的方式输出的示例中,在查询结束后,将查询结果手动的转换成了DTO对象,这种方式其实不太优雅,QueryDSL给我们提供了更好的方式,见下面的示例:
/**
* Details:方式一:使用Bean投影
*/
public List<PersonIDCardDto> findByDTOUseBean(){
Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
return queryFactory.select(
Projections.bean(PersonIDCardDto.class, QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name))
.from(QIDCard.iDCard, QPerson.person)
.where(predicate)
.fetch();
} /**
* Details:方式二:使用fields来代替setter
*/
public List<PersonIDCardDto> findByDTOUseFields(){
Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
return queryFactory.select(
Projections.fields(PersonIDCardDto.class, QIDCard.iDCard.idNo, QPerson.person.address, QPerson.person.name))
.from(QIDCard.iDCard, QPerson.person)
.where(predicate)
.fetch();
} /**
* Details:方式三:使用构造方法,注意构造方法中属性的顺序必须和构造器中的顺序一致
*/
public List<PersonIDCardDto> findByDTOUseConstructor(){
Predicate predicate = (QPerson.person.id.intValue()).eq(QIDCard.iDCard.person.id.intValue());
return queryFactory.select(
Projections.constructor(PersonIDCardDto.class, QPerson.person.name, QPerson.person.address, QIDCard.iDCard.idNo))
.from(QIDCard.iDCard, QPerson.person)
.where(predicate)
.fetch();
}
上面只是提供了几种思路,当然,还可以使用@QueryProjection来实现,非常灵活。
一对多示例:
package com.chhliu.springboot.jpa.repository; import java.util.List; import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import com.chhliu.springboot.jpa.entity.QOrder;
import com.chhliu.springboot.jpa.entity.QOrderItem;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory; @Component
public class OrderAndOrderItemManager { @Autowired
@PersistenceContext
private EntityManager entityManager; private JPAQueryFactory queryFactory; @PostConstruct
public void init() {
queryFactory = new JPAQueryFactory(entityManager);
} /**
* Details:一对多,条件查询
*/
public List<Tuple> findOrderAndOrderItemByOrderName(String orderName){
//添加查询条件
Predicate predicate = QOrder.order.orderName.eq(orderName);
JPAQuery<Tuple> jpaQuery = queryFactory.select(QOrder.order, QOrderItem.orderItem)
.from(QOrder.order, QOrderItem.orderItem)
.where(QOrderItem.orderItem.order.id.intValue().eq(QOrder.order.id.intValue()), predicate); //拿到结果
return jpaQuery.fetch();
} /**
* Details:多表连接查询
*/
public List<Tuple> findAllByOrderName(String orderName){
//添加查询条件
Predicate predicate = QOrder.order.orderName.eq(orderName);
JPAQuery<Tuple> jpaQuery = queryFactory.select(QOrder.order, QOrderItem.orderItem)
.from(QOrder.order, QOrderItem.orderItem)
.rightJoin(QOrder.order)
.on(QOrderItem.orderItem.order.id.intValue().eq(QOrder.order.id.intValue()));
jpaQuery.where(predicate);
//拿到结果
return jpaQuery.fetch();
}
}
链接
spring boot-jpa整合QueryDSL来简化复杂操作
Spring Boot JPA - 使用 Querydsl 处理复杂的操作
JPA 复杂查询 - Querydsl的更多相关文章
- Spring JPA 定义查询方法
Spring JPA 定义查询方法 翻译:Defining Query Methods 存储库代理有两种方式基于方法名派生特定域的查询方式: 直接从方法名派生查询 自定义查询方式 可用选项基于 ...
- Spring Data JPA 简单查询--接口方法
一.接口方法整理速查 下表针对于简单查询,即JpaRepository接口(继承了CrudRepository接口.PagingAndSortingRepository接口)中的可访问方法进行整理.( ...
- spring data jpa 分页查询
https://www.cnblogs.com/hdwang/p/7843405.html spring data jpa 分页查询 法一(本地sql查询,注意表名啥的都用数据库中的名称,适用于特 ...
- 第11章—使用对象关系映射持久化数据—SpringBoot+SpringData+Jpa进行查询修改数据库
SpringBoot+SpringData+Jpa进行查询修改数据库 JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分.但它又不限于EJB 3.0,你可以在Web应用.甚至桌面应用 ...
- JPA criteria 查询:类型安全与面向对象
参考:https://my.oschina.net/zhaoqian/blog/133500 一.JPA元模型概念,及使用 在JPA中,标准查询是以元模型的概念为基础的.元模型是为具体持久化单元的受管 ...
- spring data jpa 动态查询(工具类封装)
利用JPA的Specification<T>接口和元模型就实现动态查询了.但是这样每一个需要动态查询的地方都需要写一个这样类似的findByConditions方法,小型项目还好,大型项目 ...
- springboot整合spring data jpa 动态查询
Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询,在实现动态查询时我们需要用到Criteria API,主要是以下三个: 1.Criteria ...
- springboot集成Spring Data JPA数据查询
1.JPA介绍 JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.它的出现主要是为 ...
- spring data JPA entityManager查询 并将查询到的值转为实体对象
spring data JPA entityManager查询 并将查询到的值转为实体对象 . https://blog.csdn.net/qq_34791233/article/details/81 ...
随机推荐
- CentOS下的IPMI尝试
1.载入支持 ipmi 功能的系统模块 modprobe ipmi_msghandler modprobe ipmi_devintf modprobe ipmi_poweroff modprobe i ...
- FlashCache初体验
注意: 测试用的是CentOS6.5 内核版本2.6.32-431.el6.x86_64 步骤: 上传CentOS6.5做本地yum源,安装以下包. yum install gcc yum insta ...
- c++11-17 模板核心知识(十一)—— 编写泛型库需要的基本技术
Callables 函数对象 Function Objects 处理成员函数及额外的参数 std::invoke<>() 统一包装 泛型库的其他基本技术 Type Traits std:: ...
- Unity使用transform.Rotate进行三维旋转角度出现偏差
Unity使用transform.Rotate进行三维旋转角度出现偏差 情形 最开始遇到该问题的情况比较复杂,另写了一个例子.情形如下: 一个立方体上挂载脚本: transform.Rotate(25 ...
- charles功能(四) 模拟 接口404/403返回值(blacklist方法)
1.tools-->blacklist 2.允许启用黑名单选择接口返回错误的形式 (404或者403),添加接口地址并保存 3.再次请求效果如下
- PyQt学习随笔:ListView控件删除一项列表项的方法
ListView控件可以通过控件对应数据存储删除列表项,具体使用: 数据存储.removeRow(元素索引位置) 删除指定位置的一个列表项. 数据存储如果不知道程序定义的数据存储名,可以通过model ...
- pycharm执行报错: unprintable file name [Errno 2] No such file
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 老猿在pycharm执行一个工程文件testListView时,发现其工程文件对应的py文件没有后缀 ...
- Hbase API 多条件查询
public static ResultScanner scan(String tableName, String family, List<String> columns, List&l ...
- Kubernetes 教程:在 Containerd 容器中使用 GPU
原文链接:https://fuckcloudnative.io/posts/add-nvidia-gpu-support-to-k8s-with-containerd/ 前两天闹得沸沸扬扬的事件不知道 ...
- Panda Global 要点聚焦,区块链在数字医疗的落地应
据Panda Global,随着区块链技术影响力的不断扩大,其应用性已涉及更加广泛的领域,不断更新着人们的认知.在区块链技术未介入之前,关于医疗行业和数字经济结合早已不是什么新鲜话题,相关研究不少 但 ...