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);
Query objects use SQL or Hibernate Query Language (HQL) string to retrieve data from the database and create objects. A Query instance is used to bind query parameters, limit the number of results returned by the query, and finally to execute the query.
If a given JPA GROUP BY query returns only two columns where one is unique, it's very suitable to return the result as a Java Map. For this, you can use either the Java Stream functionality or the Hibernate-specific ResultTransformer .
Define Hibernate Mapping FileThe <class> elements are used to define specific mappings from a Java classes to the database tables. The Java class name is specified using the name attribute of the class element and the database table name is specified using the table attribute.
There is no standard way to get JPA to return a map. Iterating manually should be fine. The time to iterate a list/map in memory is going to be small relative to the time to execute/return the query results.
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With