gpt4 book ai didi

java - Hibernate ResultTransformer 无法转换单个列

转载 作者:行者123 更新时间:2023-11-30 10:55:17 24 4
gpt4 key购买 nike

我有一些非常复杂的 SQL(进行一些聚合,一些基于最大值的计数等)所以我想使用 SQLQuery 而不是 Query。我创建了一个非常简单的 Pojo:

public class SqlCount {
private String name;
private Double count;
// getters, setters, constructors etc

然后当我运行我的 SQLQuery 时,我希望 hibernate 为我填充一个列表,所以我这样做:

Query hQuery = sqlQuery.setResultTransformer(Transformers.aliasToBean(SqlCount.class));

现在我遇到了一个问题,根据“计数”的值,Hibernate 会以 Long、Double、BigDecimal 或 BigInteger 的形式可变地检索它。所以我使用 addScalar 函数:

sqlQuery.addScalar("count", StandardBasicTypes.DOUBLE);

现在是我的问题。似乎如果您不使用 addScalar 函数,Hibernate 将使用 SQL 结果中的所有列填充您的所有字段(即,它将尝试填充“名称”和“计数”)。但是,如果您使用 addScalar 函数,它只会映射您列出的列,所有其他列似乎都被丢弃并且字段保留为空。在这种情况下,只列出“名称”和“计数”并不会太糟糕,但我有一些其他情况需要十几个字段 - 我真的必须将它们全部列出吗? hibernate 中是否有某种方式可以说“自动映射所有字段,就像您以前那样,但顺便将此字段映射为 Double”?

最佳答案

Is there some way in hibernate to say "map all fields automatically.

没有,查文档here , 找到 16.1.1。标量查询部分

The most basic SQL query is to get a list of scalars (values).

sess.createSQLQuery("SELECT * FROM CATS").list();
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();

These will return a List of Object arrays (Object[]) with scalar values for each column in the CATS table. Hibernate will use ResultSetMetadata to deduce the actual order and types of the returned scalar values. To avoid the overhead of using ResultSetMetadata, or simply to be more explicit in what is returned, one can use addScalar():

sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
.addScalar("NAME", Hibernate.STRING)
.addScalar("BIRTHDATE", Hibernate.DATE)

我使用这个解决方案,我希望它对你有用。

使用此解决方案,您可以填充从 SQL 中选择的内容,并将其作为 Map 返回,并直接转换值。

自 hibernate 5.2 以来,方法 setResultTransformer() 已被弃用,但它对我来说工作正常并且工作完美。

如果您不喜欢为 SQL 中的每一列编写额外的代码addScalar(),您可以实现ResultTransformer 接口(interface)并按照您的意愿进行转换。

例如:假设我们有这个查询:

/*ORACLE SQL*/

SELECT
SEQ AS "code",
CARD_SERIAL AS "cardSerial",
INV_DATE AS "date",
PK.GET_SUM_INV(SEQ) AS "sumSfterDisc"
FROM INVOICE
ORDER BY "code";

注意:我对区分大小写的列别名使用了 double cote,检查 This

创建 hibernate session 后,您可以像这样创建查询:

/*Java*/

List<Map<String, Object>> list = session.createNativeQuery("SELECT\n" +
" SEQ AS \"code\",\n" +
" CARD_SERIAL AS \"cardSerial\",\n" +
" INV_DATE AS \"date\",\n" +
" PK.GET_SUM_INV(SEQ) AS \"sumSfterDisc\"\n" +
"FROM INVOICE\n" +
"ORDER BY \"code\"")
.setResultTransformer(new Trans())
.list();

现在是Trans类的重点:

/*Java*/

public class Trans implements ResultTransformer {

private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);

@Override
public Object transformTuple(Object[] objects, String[] strings) {

Map<String, Object> map = new LinkedHashMap<>();
for (int i = 0; i < strings.length; i++) {

if (objects[i] == null) {
continue;
}

if (objects[i] instanceof BigDecimal) {
map.put(strings[i], ((BigDecimal) objects[i]).longValue());
} else if (objects[i] instanceof Timestamp) {
map.put(strings[i], dateFormat.format(((Timestamp) objects[i])));
} else {
map.put(strings[i], objects[i]);
}
}
return map;
}

@Override
public List transformList(List list) {
return list;
}
}

这里你应该覆盖两个方法transformTupletransformList,在transformTuple你有两个参数Object[]对象它行的列值String[] strings 列的名称 hibernate 保证 列的顺序与您在查询。

现在有趣的事情开始了,对于从查询返回的每一行,方法 transformTuple 将被调用,因此您可以将行构建为 Map 或使用字段创建新对象.

关于java - Hibernate ResultTransformer 无法转换单个列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33392539/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com