关于JPA entityManager查询出数据转为List<Map>的详细说明

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]);
            }
        }

这里我是转为大写,需要转换为其他的格式可以自己做另外的操作。

自己也是个小白,写博客的目的第一是想记录一下平常的问题,第二就是想让各位大神批评指教,有什么说错的地方或者有误导他人的地方希望大家及时给我指出来,如果有不喜欢的勿喷,谢谢。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值