Hibernate SQL 查询结果 Mapping/Convert TO Object/Class/Bean
Posted
技术标签:
【中文标题】Hibernate SQL 查询结果 Mapping/Convert TO Object/Class/Bean【英文标题】:Hibernate SQL Query result Mapping/Convert TO Object/Class/Bean 【发布时间】:2013-06-25 17:05:06 【问题描述】:1 2: select(table.*)/(all column) 就OK了
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。 喜欢:Student[id=?, name=?, sex=?, (其他字段为空/默认)] 我不知道这个错误,请帮助我!
【问题讨论】:
为什么使用sql查询?什么时候可以使用 hql 或标准?你把hql
而不是 sql
在 3 一个错误:P
哈哈!我只是展示一个示例。实际上,有些业务必须通过sql实现。
【参考方案1】:
只有两种方法。
您可以使用第一个或第二个 sn-p。根据 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();
【讨论】:
谢谢。在addScalar之后使用query.setResultTransformer(custom transformer),可以转换成Student.class,但我不想这样。 我希望它是 Student 的 Object 实例,有人知道吗?【参考方案2】:您可以进一步添加
.setResultTransformer(Transformers.aliasToBean(YOUR_DTO.class));
并自动将其映射到您的自定义 dto 对象,另请参阅 Returning non-managed entities。
例如:
public List<MessageExtDto> 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<MessageExtDto> list = query.list();
return list;
【讨论】:
应该很有用,但是我太懒了,还以为可以自动转换呢。【参考方案3】:我想让“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<Student> students = query.getResultList();
for (Student s : students)
s.getName(); // ...
注意:我认为无法避免未经检查的警告。
【讨论】:
【参考方案4】:我在 HQL 查询上遇到了同样的问题。我通过更换变压器解决了这个问题。
该问题导致编写的代码转换为 Map。但它不适用于 Alias Bean。您可以在下面看到错误代码。将结果转换为地图并将新字段放入地图的代码。
类:org.hibernate.property.access.internal.PropertyAccessMapImpl.SetterImpl 米 方法:设置
@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<String, Field> 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));
【讨论】:
找不到 io.robe.hibernate.criteria.api.query.SearchQuery 你能在这方面帮忙吗?我用这个链接mvnrepository.com/artifact/io.robe/robe-hibernate/0.5.0.0-1039【参考方案5】:您可以自动映射它:
你的模型 Student.java
公开课学生 私有字符串名称; 私有字符串地址;
存储库
String sql = "Select * from student"; 查询查询 = em.createNativeQuery(sql, Student.class); 列表 ls = query.getResultList();
【讨论】:
以上是关于Hibernate SQL 查询结果 Mapping/Convert TO Object/Class/Bean的主要内容,如果未能解决你的问题,请参考以下文章
hibernate使用setResultTransformer()将SQL查询结果放入集合中
使用hibernate原生sql查询,结果集全为1的问题解决