Retrieve a row from DB as a Map in Hibernate

Table Players:

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

This table is where instances of class Player are persisted (one row per instance, no composition etc.).

Having a Hibernate Session, how do I get the row (say with id - the PK - equal to 1) as a Java Map (key = column name, value = cell value) ?

Example usage:

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

Answers


Use a query with AliasToEntityMapResultTransformer; is verbose but should works with Hibernate property definition and not with JavaBean definition (they can differ).

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();

A worse approch can be write a custom ResultTransformer that introspect ClassMetadata and try to extract values...

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

and use

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

Last chance:

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

but this doesn't map list,bags and other mapped object, but only raw column names and values...


You can use HQL and do a query for selecting the result as a new Map

select new Map(p.id as ID, p.name as name, p.email as email, p.age as age)
from Player p

It will return you a collection of maps, being each one of the maps a row in the query result.


You can use BeanUtils and do something like this:

User user = (User) session.get(User.class, userID);
Map map = BeanUtils.describe(user);

Need Your Help

How to post code in SO

support markdown code-formatting

I got tired to put code in SO. The four indentations I made is not working. For example, I am posting below line with four spaces forth and the back.

Cython dictionary / map

python dictionary cython

I have a list of element, label pairs like this: [(e1, l1), (e2, l2), (e3, l1)]