在JPA中我们可以使用entityManager.createNativeQuery()来执行原生的SQL语句,并且JPA的底层实现都是支持返回Map对象的。例如:
EclipseLink 的 query.setHint(QueryHints.RESULT_TYPE, ResultType.Map);
Hibernate 的query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
OpenJPA 的 QueryImpl impl = q.unwrap(QueryImpl.class); impl.setResultClass(Map.class);
本文中使用的是Spring Data JPA(Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现),遂用 Hibernate 的query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)。
1.工具类
@Component
public class EntityManagerUtil<T> {
@PersistenceContext
private EntityManager entityManager;
//1.返回map
public List<Map<String, Object>> getListMap(String sql){
Query nativeQuery=entityManager.createNativeQuery(sql);
nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
List resultList=nativeQuery.getResultList();
return resultList;
}
//2.返回自定义实体类
public List<T> nativeQueryResult(String sql, Class clazz) {
sql = Normalizer.normalize(sql, Normalizer.Form.NFKC);
sql = sql.replaceAll(".*([';]+|(--)+).*", "");
Query query = entityManager.createNativeQuery(sql);
List<T> queryList = query.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(clazz)).list();
return queryList;
}
}
2.具体应用
//1.自动注入
@Autowired
private EntityManagerUtil entityManagerUtil;
//1.返回map
String sql="sql语句";
List<Map> list=entityManagerUtil.getListMap(sql);
//2.1 返回自定义实体类(方法一)
List<实体类> list = entityManagerUtil.nativeQueryResult(sql, 实体类.class);
//2.2 返回自定义实体类(方法二 hql)
https://www.cnblogs.com/jpfss/p/11162135.html
在hql中使用 select new 包名.类名(属性1,属性2……) from 实体类,同时在实体类中添加带参的构造方法,参数的个数和顺序与(属性1,属性2……) 保持一致,这样我们得到的list中存放的依然是实体类的对象,所查询到的属性得到了填充。
参考:
JPA、Hibernate、Spring data jpa之间的关系
https://www.cnblogs.com/jpfss/p/11162135.html