select firstName, lastName from Employee
query.setResultTransformer(Transformers.aliasToBean(MyResults.class));
由于异常,您不能将上述代码用于 Hibernate 5 和 Hibernate 4(至少是 Hibernate 4.3.6.Final)
java.lang.ClassCastException: com.github.fluent.hibernate.request.persistent.UserDto cannot be cast to java.util.Map
at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102)
问题在于 Hibernate 将列名的别名转换为大写——firstName 变为 FIRSTNAME。它会尝试使用此类策略在DTO 中查找名称为getFIRSTNAME() 的getter 和setter setFIRSTNAME()
PropertyAccessStrategyChainedImpl propertyAccessStrategy = new PropertyAccessStrategyChainedImpl(
PropertyAccessStrategyBasicImpl.INSTANCE,
PropertyAccessStrategyFieldImpl.INSTANCE,
PropertyAccessStrategyMapImpl.INSTANCE
);
在 Hibernate 看来,只有 PropertyAccessStrategyMapImpl.INSTANCE 适合。所以之后它会尝试进行转换(Map)MyResults。
public void set(Object target, Object value, SessionFactoryImplementor factory) {
( (Map) target ).put( propertyName, value );
}
不知道,这是一个错误或功能。
如何解决
使用带引号的别名
public class Results {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
String sql = "select firstName as \"firstName\",
lastName as \"lastName\" from Employee";
List<Results> employees = session.createSQLQuery(sql).setResultTransformer(
Transformers.aliasToBean(Results.class)).list();
使用自定义结果转换器
解决问题的另一种方法——使用忽略方法名称大小写的结果转换器(将getFirstName() 视为getFIRSTNAME())。您可以自己编写或使用FluentHibernateResultTransformer。您将不需要使用引号和别名(如果您的列名等于 DTO 名称)。
只需从项目页面下载库(不需要额外的 jar):fluent-hibernate。
String sql = "select firstName, lastName from Employee";
List<Results> employees = session.createSQLQuery(sql)
.setResultTransformer(new FluentHibernateResultTransformer(Results.class))
.list();
这个转换器也可以用于嵌套投影:How to transform a flat result set using Hibernate