SpringBoot JPA实践之EntityManage查询返回自定义DTO的代理实现
JPA动态代理admin 发布于:2020-05-01 22:14:39
阅读:loading
根据前文中的代码实现示例,将实现一个接口代理查询返回自定义DTO的实现,与JPA自带的@Query查询实现类似,主要是将SQL查询出的结果集转换为普通Bean对象,依赖EntityManager对象提供的方法,自动将查询的结果集映射为Map<String,Object>、DTO、List<Map<String,Object>>、List<DTO>,具体使用参考如下。
package cn.chendd.example.jpa.user.repository;
import cn.chendd.example.jpa.nativequery.annotions.Query;
import cn.chendd.example.jpa.nativequery.annotions.QueryResult;
import cn.chendd.example.jpa.nativequery.enums.ResultSetType;
import cn.chendd.example.jpa.user.dao.NaiveQueryForMapDao;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Map;
/**
* @author chendd
* @date 2020/5/6 23:19
*/
public interface MapResultSqlQuery {
@Query(sql = "select * from user limit 1" , entityManager = NaiveQueryForMapDao.class ,
resultSet = @QueryResult(resultSetType = ResultSetType.Map))
Map<String , Object> queryForMap();
@Query(sql = "select * from user" , entityManager = NaiveQueryForMapDao.class ,
resultSet = @QueryResult(resultSetType = ResultSetType.Map))
List<Map<String , Object>> queryForList();
@Query(sql = "select * from user where name = :name " , entityManager = NaiveQueryForMapDao.class ,
resultSet = @QueryResult(resultSetType = ResultSetType.Map))
List<Map<String , Object>> queryForList(@Param("name") String name);
@Query(sql = "select * from user where (name = :name or :name is null) " +
"and (:sexFlag is null or sex in (:sexList))" , entityManager = NaiveQueryForMapDao.class ,
resultSet = @QueryResult(resultSetType = ResultSetType.Map))
List<Map<String, Object>> queryForList(@Param("name") String name , @Param("sexFlag") String sexFlag, @Param("sexList") List<String> sexList);
}
package cn.chendd.example.jpa.user.repository;
import cn.chendd.example.jpa.nativequery.annotions.Query;
import cn.chendd.example.jpa.nativequery.annotions.QueryResult;
import cn.chendd.example.jpa.user.dao.NaiveQueryForBeanDao;
import cn.chendd.example.jpa.user.dto.UserResultDto;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* @author chendd
* @date 2020/5/11 22:36
*/
public interface BeanResultSqlQuery {
@Query(sql = "select 88911 id , 'chendd' userName , now() createTime , 88911.006 amount , " +
" 3.1415926 pi , 1 status", entityManager = NaiveQueryForBeanDao.class)
UserResultDto queryForBean();
@Query(sql = "select 88911 id , 'chendd' userName , now() createTime , 88911.006 amount , " +
" 3.1415926 pi , 1 status" , entityManager = NaiveQueryForBeanDao.class)
List<UserResultDto> queryForList();
@Query(sql = "select * from (" +
"select 1 id , 'chen11' userName , now() createTime " +
" union all " +
"select 2 id , 'chen22' userName , now() createTime " +
" union all " +
"select 3 id , 'chen33' userName , now() createTime " +
" union all " +
"select 4 id , 'chen44' userName , now() createTime " +
") newTab" , entityManager = NaiveQueryForBeanDao.class
, resultSet = @QueryResult(include = {"id" , "userName" , "createTime"}))
List<UserResultDto> queryForListForPart();
@Query(sql = "select * from (" +
"select 1 id , 'chen11' userName , now() createTime " +
" union all " +
"select 2 id , 'chen22' userName , now() createTime " +
" union all " +
"select 3 id , 'chen33' userName , now() createTime " +
" union all " +
"select 4 id , 'chen44' userName , now() createTime " +
") newTab where id > :id and (:name is null or userName like concat(:name,'%'))"
, entityManager = NaiveQueryForBeanDao.class
, resultSet = @QueryResult(include = {"id" , "userName" , "createTime"}))
List<UserResultDto> queryForListForParam(@Param("id") Long userId , @Param("name") String userName);
@Query(sql = "select a.name userName from ${value(spring.jpa.properties.hibernate.default_catalog) , after(.)}user a " +
" where 1=1 limit :limit"
, entityManager = NaiveQueryForBeanDao.class
, resultSet = @QueryResult(include = "userName")
)
List<UserResultDto> queryForListForVariableParam(@Param("limit") Long limit);
}
package cn.chendd.example.jpa.user.dto;
import cn.chendd.example.jpa.nativequery.annotions.Column;
import lombok.Data;
import org.hibernate.type.StringType;
import java.math.BigDecimal;
import java.sql.Timestamp;
/**
* UserResultDto
*
* @author chendd
* @date 2020/5/6 0:29
*/
@Data
public class UserResultDto {
@Column
private Long id;
@Column(name = "userName" , type = StringType.class)
private String userName;
@Column
private Timestamp createTime;//或者Date类型
@Column
private BigDecimal amount;
@Column
private Double pi;
@Column
private Boolean status;
}
@Query
sql:提供SQL语句,支持动态SQL查询与内置变量替换;
entityManager:entityManager是一个线程不安全对象,通常也涉及到具体的数据源,故需要调用者提供,与DAO中提供数据源DataSource一样,代码中有提供基于base的实现可参考;
QueryResult:查询返回的结果集绑定,不指定该参数,默认返回DTO类型;
@QueryResult
查询返回的结果集类型,默认返回DTO类型,且包含DTO所有的属性,查询返回的字段名称为DTO中定义的属性名称,字段值类型为属性定义类型,也可以手动指定返回的结果集类型(Map或DTO);考虑到某个DTO如果想多个复用的场景,提供了一个includes的实现,将只对限定的某些属性生效;
@Param
JPA-hibernate提供的注解;
@Column
name:查询SQL中的字段名称,与DTO中定义的属性名称对应,指定后优先按指定设置;
type:查询列对应的Hibernate类型,默认不指定将根据DTO属性类型自动转换为Hibernate对应类型,指定后优先按指定设置,具体转换的类型可参考本系列文章小技巧篇提供的API地址;
(1)方法返回值按约定定义,常见的查询返回一条数据与多条数据,即Map与List类型结果集,当方法的返回值类型为List结构时,调用entityManage.getResultList方法;否则调用entityManager.getSingleResult;
(2)调用逻辑参考JPA提供的@Query查询实现,学习成本较低;
(3)内置动态参数绑定方式,使用规范与JPA提供@Query的三种参数传递方式一致(个人觉得最佳的一种方式,三种方式本站的JPA系列文章有详细说明),即“@Param注解 + :属性名”的方式;
(4)支持内置变量替换,${} 部分支持三个内置函数: before 、value、after,其中value为 application .yml文件中的key,before与after分别为value值的插入与追加的文本;
(1)目前为增加关于分页的查询实现;
(2)调用的类或方法当前必须为事物只读;
另有一种直接使用Spring AOP的代理实现,直接拦截所有Jpa的Repository,实现方法的自定义实现即可。
点赞
发表评论
评论列表
留言区
- Java动态代理之实现方法拦截
- Java动态代理之接口实现
- SpringBoot JPA实践之框架搭建
- SpringBoot JPA实践之BaseRepository
- SpringBoot JPA实践之自动生成Entity
- SpringBoot JPA实践之API介绍
- SpringBoot JPA实践之方法属性名查询
- SpringBoot JPA实践之Example对象查询
- SpringBoot JPA实践之Named查询
- SpringBoot JPA实践之@Query查询之参数传参方式
- SpringBoot JPA实践之@Query查询之动态查询条件
- SpringBoot JPA实践之@Query查询之接口结果集
- SpringBoot JPA实践之@Query查询之分页实现
- SpringBoot JPA实践之EntityManage查询返回自定义DTO
- SpringBoot JPA实践之Specification查询分页
- SpringBoot JPA实践之表达式自定义属性与方法
- SpringBoot JPA实践之小技巧汇总
- java动态代理简单例子