Hibernate SQL查询结果映射/转换为对象/类/ Bean

1 2:select(table。*)/(all column)没问题

String sql = "select t_student.* from t_student"; //String sql = "select t_student.id,t_student.name,... from t_student"; //select all column SQLQuery query = session.createSQLQuery(sql); query.addEntity(Student.class);//or query.addEntity("alias", Student.class); //query.list();[Student@..., Student@..., Student@...] query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); //or other transformer query.list(); //[{Student(or alias)=Student@...},{Student=Student@...}] 

3:选择一些列(不是全部),是错误

 String sql = "select t_student.id,t_student.name.t_student.sex from t_student"; SQLQuery query = session.createSQLQuery(sql); query.addEntity(Student.class); query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); query.list(); //Exception:invalid column/no column 

我希望“3”正常工作,并将结果映射到Student.class。
喜欢:学生[id =?,name =?,sex =?,(其他字段为null /默认)]
我不知道这个错误,请帮帮我!

你可以进一步添加.setResultTransformer(Transformers.aliasToBean(YOUR_DTO.class)); 并自动将其映射到您的自定义dto对象,另请参阅返回非托管实体 。

例如:

 public List getMessagesForProfile2(Long userProfileId) { Query query = getSession().createSQLQuery(" " + " select a.*, b.* " + " from messageVO AS a " + " INNER JOIN ( SELECT max(id) AS id, count(*) AS count FROM messageVO GROUP BY messageConversation_id) as b ON a.id = b.id " + " where a.id > 0 " + " ") .addScalar("id", new LongType()) .addScalar("message", new StringType()) ......... your mappings .setResultTransformer(Transformers.aliasToBean(MessageExtDto.class)); List list = query.list(); return list; } 

只有两种方式。

您可以使用第1或第2个片段。 根据Hibernate文档,您必须选择2nd。

你只能获得一个对象数组列表,如下所示:

 String sql = "select name, sex from t_student"; SQLQuery query = session.createSQLQuery(sql); query.addScalar("name", StringType.INSTANCE); query.addScalar("sex", StringType.INSTANCE); query.list(); 

我希望“3”正常工作,并将结果映射到Student.class

这是可能的使用
Query createNativeQuery(String sqlString, String resultSetMapping

在第二个参数中,您可以告诉结果映射的名称。 例如:

1)让我们考虑一个Student实体,魔法将在SqlResultSetMapping注释中:

 import javax.persistence.Entity; import javax.persistence.SqlResultSetMapping; import javax.persistence.Table; @Entity @Table(name = "student") @SqlResultSetMapping(name = "STUDENT_MAPPING", classes = {@ConstructorResult( targetClass = Student.class, columns = { @ColumnResult(name = "name"), @ColumnResult(name = "address") })}) public class Student implements Serializable { private String name; private String address; /* Constructor for the result mapping; the key is the order of the args*/ public Student(String aName, String anAddress) { this.name = aName; this.address = anAddress; } // the rest of the entity } 

2)现在您可以执行一个查询,结果将由STUDENT_MAPPING逻辑映射:

 String query = "SELECT s FROM student s"; String mapping = "STUDENT_MAPPING"; Query query = myEntityManager.createNativeQuery(query, mapping); @SuppressWarnings("unchecked") List students = query.getResultList(); for (Student s : students) { s.getName(); // ... } 

注意 :我认为不可能避免未经检查的警告。

我在HQL查询上遇到了同样的问题。 我通过更换变压器解决了这个问题。

该问题导致编写的代码转换为Map。 但它不适合Alias Bean。 您可以在下面看到错误代码。 写入的代码将结果作为map并将新字段放入地图。

类:org.hibernate.property.access.internal.PropertyAccessMapImpl.SetterImpl m方法:设置

  @Override @SuppressWarnings("unchecked") public void set(Object target, Object value, SessionFactoryImplementor factory) { ( (Map) target ).put( propertyName, value ); } 

我解决了复制变换器和更改代码的问题。

您可以在项目中看到代码。

链接: https : //github.com/robeio/robe/blob/DW1.0-migration/robe-hibernate/src/main/java/io/robe/hibernate/criteria/impl/hql/AliasToBeanResultTransformer.java

类:

 import java.lang.reflect.Field; import java.util.Map; import io.robe.hibernate.criteria.api.query.SearchQuery; import org.hibernate.HibernateException; import org.hibernate.transform.AliasedTupleSubsetResultTransformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AliasToBeanResultTransformer extends AliasedTupleSubsetResultTransformer { private static final Logger LOGGER = LoggerFactory.getLogger(AliasToBeanResultTransformer.class); private final Class resultClass; // Holds fields of Transform Class as Map. Key is name of field. private Map fieldMap; public AliasToBeanResultTransformer(Class resultClass) { if ( resultClass == null ) { throw new IllegalArgumentException( "resultClass cannot be null" ); } fieldMap = SearchQuery.CacheFields.getCachedFields(resultClass); this.resultClass = resultClass; } @Override public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) { return false; } @Override public Object transformTuple(Object[] tuple, String[] aliases) { Object result; try { result = resultClass.newInstance(); for ( int i = 0; i < aliases.length; i++ ) { String name = aliases[i]; Field field = fieldMap.get(name); if(field == null) { LOGGER.error(name + " field not found in " + resultClass.getName() + " class ! "); continue; } field.set(result, tuple[i]); } } catch ( InstantiationException e ) { throw new HibernateException( "Could not instantiate resultclass: " + resultClass.getName() ); } catch ( IllegalAccessException e ) { throw new HibernateException( "Could not instantiate resultclass: " + resultClass.getName() ); } return result; } } 

创建新的Transformer之后你可以使用如下。

 query.setResultTransformer(new AliasToBeanResultTransformer(YOUR_DTO.class));