emmm…最近使用JPA的时候遇到了这么个问题,基于公司使用数据库不同的要求,我们不用Dao层的@Query注解实现复杂的SQL,所以就开始研究entityManager,在使用entityManager时遇到的问题就是默认返回的getResultList()时List类型,那当我想返回MAP类型时怎么处理呢?
首先最重要的就是注入entityManager
//注入entityManager
@PersistenceContext(type = PersistenceContextType.EXTENDED)
EntityManager entityManager;
// 正常返回List的情况
String sql = "select code from qj where id in(?1) "
Query query= entityManager.createNativeQuery(sql );
query.setParameter(1,array);
List <String> list = query.getResultList();
需要注意的是sql 防止注入时 in 后面需要写上索引位置,query.getResultList()返回的是一个List<Object[]>。这样的结果肯定不满足我们的需求的,那么当我们想返回的结果变成Map该怎么做呢?
String sql = "select * from qj where id in(?1) "
Query query= entityManager.createNativeQuery(sql );
query.setParameter(1,array);
query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
List<Map> resultList = query.getResultList();
通过以上方法 就可以把返回的结果集转换成Map类型的List,当然还有一种方式已经过时了,我们这边就不赘述了。
重点来了,以上返回的Map 所有的Key的大小写是根据数据库决定的,根据源码可以看到具体操作
源码如下:
package org.hibernate.transform;
public final class Transformers {
public static final AliasToEntityMapResultTransformer ALIAS_TO_ENTITY_MAP;
public static final ToListResultTransformer TO_LIST;
private Transformers() {
}
public static ResultTransformer aliasToBean(Class target) {
return new AliasToBeanResultTransformer(target);
}
static {
ALIAS_TO_ENTITY_MAP = AliasToEntityMapResultTransformer.INSTANCE;
TO_LIST = ToListResultTransformer.INSTANCE;
}
}
package org.hibernate.transform;
import java.util.HashMap;
import java.util.Map;
public class AliasToEntityMapResultTransformer extends AliasedTupleSubsetResultTransformer {
public static final AliasToEntityMapResultTransformer INSTANCE = new AliasToEntityMapResultTransformer();
private AliasToEntityMapResultTransformer() {
}
public Object transformTuple(Object[] tuple, String[] aliases) {
Map result = new HashMap(tuple.length);
for(int i = 0; i < tuple.length; ++i) {
String alias = aliases[i];
if (alias != null) {
result.put(alias, tuple[i]);
}
}
return result;
}
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
return false;
}
private Object readResolve() {
return INSTANCE;
}
}
可以看到Transformers 里的静态代码块里的操作就是转换map
ALIAS_TO_ENTITY_MAP = AliasToEntityMapResultTransformer.INSTANCE;
继续跟进去可以看到
for(int i = 0; i < tuple.length; ++i) {
String alias = aliases[i];
if (alias != null) {
result.put(alias, tuple[i]);
}
这就是转换的源码,转换后默认的key大小写是根据数据库决定的,那么我们就遇到了这个问题,当我们的数据库为Orcle的时候,返回的Key为大写,像postgre的话是小写的,那我们用到什么样的数据库决定返回得大小写,直接影响到我们后续取key和value,那该怎么解决呢?比较难受得方法是把List遍历,把里面所有得key手动转换大写,其次得话就用三元去判断小写取不到就取大写,这样很影响效率。这里推荐一个方法就是修改他得源码,当然不能直接修改源码,那我们直接自己创建两个类似得类,去处理相关逻辑,就可以实现统一返回大写或者小写。
代码如下:
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.transform.ResultTransformer;
public class OffersetTransformers {
public static final AliasToEntityMapResultTransformer ALIAS_TO_ENTITY_MAP;
private OffersetTransformers() {
}
public static ResultTransformer aliasToBean(Class target) {
return new AliasToBeanResultTransformer(target);
}
static {
ALIAS_TO_ENTITY_MAP = AliasToEntityMapResultTransformer.INSTANCE;
}
}
import org.hibernate.transform.AliasedTupleSubsetResultTransformer;
import java.util.HashMap;
import java.util.Map;
public class AliasToEntityMapResultTransformer extends AliasedTupleSubsetResultTransformer {
public static final AliasToEntityMapResultTransformer INSTANCE = new AliasToEntityMapResultTransformer();
private AliasToEntityMapResultTransformer() {
}
public Object transformTuple(Object[] tuple, String[] aliases) {
Map result = new HashMap(tuple.length);
for(int i = 0; i < tuple.length; ++i) {
String alias = aliases[i];
if (alias != null) {
result.put(alias.toUpperCase(), tuple[i]);
}
}
return result;
}
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
return false;
}
private Object readResolve() {
return INSTANCE;
}
}
这里我们只需要改变
query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
为我们自己重写的类
query.unwrap(NativeQueryImpl.class).setResultTransformer(OffersetTransformers .ALIAS_TO_ENTITY_MAP);
String sql = "select * from qj where id in(?1) "
Query query= entityManager.createNativeQuery(sql );
query.setParameter(1,array);
query.unwrap(NativeQueryImpl.class).setResultTransformer(OffersetTransformers.ALIAS_TO_ENTITY_MAP);
List<Map> resultList = query.getResultList();
这样的话就能统一返回的map的key的大小写,
相信大家也就看到了区别主要是在
for(int i = 0; i < tuple.length; ++i) {
String alias = aliases[i];
if (alias != null) {
result.put(alias.toUpperCase(), tuple[i]);
}
}
这里我是转为大写,需要转换为其他的格式可以自己做另外的操作。
自己也是个小白,写博客的目的第一是想记录一下平常的问题,第二就是想让各位大神批评指教,有什么说错的地方或者有误导他人的地方希望大家及时给我指出来,如果有不喜欢的勿喷,谢谢。