一尘不染

从数据库中检索一行作为Hibernate中的Map

hibernate

Players

ID | name  | email | age | ...
1  | 'bob' | null  | 23  | ...

该表是Player持久保存类实例的地方(每个实例一行,没有组成等)。

拥有Hibernate时Session如何将行 (例如id-PK-等于1) 作为Java Map获得 (键=列名,值=单元格值)?

用法示例:

Map<String,String> row = getPlayerByIdAsMap(1);

阅读 196

收藏
2020-06-20

共1个答案

一尘不染

使用查询AliasToEntityMapResultTransformer;是冗长的,但应与Hibernate属性定义一起使用,而不应与JavaBean定义一起使用(它们可以有所不同)。

Map<String,Object> aliasToValueMap = 
    session.createCriteria(User.class)
      .add(Restrictions.idEq(userID))
      .setProjection(Projections.projectionList()
        .add(Projections.id().as("id"))
        // Add others properties
      )
      .setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE)
    .uniqueResult();

更糟糕的做法是编写自定义ResultTransformer,以对ClassMetadata进行内省并尝试提取值。

class IntrospectClassMetadata extends BasicTransformerAdapter {
  PassThroughResultTransformer rt = PassThroughResultTransformer.INSTANCE;
  public Object transformTuple(Object[] tuple, String[] aliases) {
    final Object o = rt.transformTuple(tuple, aliases);
    ClassMetadata cm = sf.getClassMetadata(o.getClass());
    List<String> pns = new ArrayList<String>(Arrays.asList(cm.getPropertyNames()));
    Map<String, Object> m = new HashMap<String, Object>();
    for(String pn : pns) {
      m.put(pn, cm.getPropertyValue(o, pn));
    }
    m.put(cm.getIdentifierPropertyName(), cm.getIdentifier(o));
    return m;
  }
}

和使用

Map<String,Object> aliasToValueMap = 
        session.createCriteria(User.class)
          .add(Restrictions.idEq(userID))
          .setResultTransformer(new IntrospectClassMetadata())
        .uniqueResult();

最后的机会:

Map<String,Object> map = (Map<String,Object>)s.createSQLQuery("select * from user where id = :id")
  .setParameter("id",p.id)
  .setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE)
.uniqueResult();

但这不映射列表,包和其他映射对象,而仅映射原始列名称和值…

2020-06-20