![cec1eac099713dfaba6b0e260d4d459b.png](https://i-blog.csdnimg.cn/blog_migrate/e6dd69e1eb38e665dbdd00a94536daf1.jpeg)
业务上经常有一种场景:对多个表(实体)查询进行sql查询,然后返回都是相同格式的数据。
比如对多个表数据按日期进行统计,返回不同表每天的数据更新/创建个数。返回结果涉及多个字段,如果是单个字段,JPA在Repository类中定义@Query可以直接解决,但是返回多个字段时无法通过JPA定义接口直接返回。
对于该场景,可以使用NamedNativeQueries +SqlResultSetMapping 来解决,其中NamedNativeQueries用于标识需要进行统计查询的SQL,SqlResultSetMapping用于对结果进行统一封装。
比如:对A,B表都进行以上日期数据统计,返回结果都用类D(PairResult)来进行封装POJO
@Entity
@Table(name = "xxx_a")
@DynamicUpdate(true)
@DynamicInsert(true)
@NamedNativeQueries(
{@NamedNativeQuery(name="get7Days1",
query="select DATE_FORMAT(c_time,'%Y-%m-%d') as `date`,count(*) as cnt from xxx_a where to_days(now())-to_days(c_time)<=7 "+
"group by DATE_FORMAT(c_time,'%Y-%m-%d') order by c_time asc",
resultSetMapping="PairResult"),
@NamedNativeQuery(name = "get7Days2",
query = "select DATE_FORMAT(m_time,'%Y-%m-%d') as `date`,count(*) as cnt from xxx_a where to_days(now())-to_days(m_time)<=7 " +
"group by DATE_FORMAT(m_time,'%Y-%m-%d') order by m_time asc",
resultSetMapping = "PairResult")
})
public class A {
...
}
@Entity
@Table(name = "xxx_b")
@DynamicUpdate(true)
@DynamicInsert(true)
@NamedNativeQuery(name="get7Days3",
query = "select DATE_FORMAT(c_time,'%Y-%m-%d') as `date`,count(*) as cnt from xxx_b where to_days(now())-to_days(c_time)<=7 group by DATE_FORMAT(c_time,'%Y-%m-%d') order by c_time asc",
resultSetMapping = "PairResult")
public class B {
...
}
import javax.persistence.*;
/**
* Created by bestjimmy on 2019/1/22.
*/
@Entity
@SqlResultSetMapping(
name = "PairResult",
entities = {
@EntityResult(entityClass = PairResult.class)}
)
public class PairResult {
@Id
String date;
Long cnt;
}
其中@NamedNativeQueries 可以定义多个@NamedNativeQuery
每个@NamedNativeQuery 需要定义name(查询名称),query(SQL语句),resultSetMapping 使用哪个SqlResultSetMapping mapping结果
@SqlResultSetMapping定义了mapping的名称,entities定义使用哪个类封装返回实体
具体使用:在某个dto或dao类中,先获得实体管理实例
@PersistenceContext
private EntityManager em;
然后通过创建命名查询,即可获得结果
Query query=em.createNamedQuery("get7Days1");
List<ResultPair> list=query.getResultList();
jimmy试图想将@NamedNativeQuery能否直接迁移到JPA的DAO接口上,这样管理起来方便,但是一直未找到实现方法,因为@NamedNativeQuery必须定义在实体类上。但是可以将em.createNamedQuery(“get7Days1”); 这部分省略,直接通过JPA Repository定义,方法如下:
- 在NamedNativeQuery中加入实体类的限定
@NamedNativeQuery(name=”A.get7Days1“,
query=”select DATE_FORMAT(c_time,’%Y-%m-%d’) as `date`,count(*) as cnt from xxx_a where to_days(now())-to_days(c_time)<=7 “+
“group by DATE_FORMAT(c_time,’%Y-%m-%d’) order by c_time asc”,
resultSetMapping=”PairResult”),
2. 在jpa中定义同名方法
public interface ADao extends JpaRepository<A, String> {
List<ResultPair> get7Days1();
}
这样,可以直接通过 ADao.get7Days1() 获取结果