java - 我们如何使用 java 将复杂的 NativeQuery 结果映射到 DTO 对象

标签 java sql hibernate jpa

Query query = em.createNativeQuery(STUDENT_QUERY_WITH_PARAMS);
        query.setParameter("studentId", stduentId);
        query.setParameter("startDate", valueOf(startDate), TemporalType.DATE);
        query.setParameter("endDate", valueOf(endDate), TemporalType.DATE);
        List<Object[]> resultList = query.getResultList();

        List<StudentDepartmentCatDTO> result = new ArrayList<>(resultList.size());
        for (Object[] row : resultList) {
            result.add(new StudentDepartmentCatDTO((String)row[0], (String)row[1], (String)row[2], null,(UUID)row[4], (Integer)row[5], (Integer)row[6], (Integer)row[7], (Integer)row[8], null, null, null, null ));
        }

`我有 SQL 查询通过连接多个表(在我的例子中是 13 个表)从各个表中提取某些数据,并且我能够成功返回所有结果,但是当我尝试将这些结果映射回 DTO 时,我我遇到了强制转换异常。如何克服这些异常?

B 无法转换为类 java.util.UUID 并且 类 java.math.BigDecimal 无法转换为类 java.lang.Integer

由于所有结果都来自各个表,因此我没有找到使用 SqlResultSetMapping 执行此操作的方法,因为没有任何托管实体可以直接映射到结果。有一个更好的方法吗?我如何修复这些强制转换异常?我可以创建非托管实体以将所有结果映射到它吗?如何将 sql 结果提取到我的 DTO。

最佳答案

您可以use an @SqlResultSetMapping to convert each record in your result set to a DTO目的。但这需要一个额外的构造函数,这样您就不需要将任何参数设置为 null

下面是此类映射的示例。正如您所看到的,您需要按名称引用结果集中的元素,但您没有共享您的查询。因此,我无法根据您的查询调整示例。

@SqlResultSetMapping(
        name = "BookValueMapping",
        classes = @ConstructorResult(
                targetClass = BookValue.class,
                columns = {
                    @ColumnResult(name = "id", type = Long.class),
                    @ColumnResult(name = "title"),
                    @ColumnResult(name = "version", type = Long.class),
                    @ColumnResult(name = "authorName")}))

我将此映射与查询一起使用,该查询从以下位置选择 idtitleversionauthorName 列数据库。 @ConstructorResult 注释描述了 BookValue 类的构造函数调用。 @ColumnResult 注释定义构造函数参数及其顺序。您需要确保实例化的类提供与这些参数匹配的构造函数。

@SqlResultSetMapping 是 JPA 中强大而灵活的功能。我在这里详细解释一下:https://thoughts-on-java.org/result-set-mapping-constructor-result-mappings/

<小时/>

好的,现在让我们来看看类(class) Actor 问题......

转换失败,因为两个对象属于错误的类。 row[4] 似乎是一个 byte[] 并且 row[6/7/8] 之一(或全部)似乎成为一个 BigInteger。

此代码片段应该可以帮助您将 byte[] 转换为 UUID:

ByteBuffer bb = ByteBuffer.wrap(bytes);
long high = bb.getLong();
long low = bb.getLong();
UUID uuid = new UUID(high, low);

BigDecimal转换为Integer要容易得多。您只需调用 BigDecimal 上的 intValueExact() 方法,例如row[6].intValueExact();.

关于java - 我们如何使用 java 将复杂的 NativeQuery 结果映射到 DTO 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55621603/

相关文章:

hibernate - JPA/Hibernate 在 EJB/Seam 环境中提交时不发出 UPDATE

java - 将Kotlin项目从pom.xml转换为build.gradle

java - 通过 SOAP API 将报告部署到 JasperServer

SQL 别名无法识别

Mysql - 选择与日期范围不匹配的行?

java - 在 Hibernate 中创建列类型 Datetime

java - TextView 不使用 Html.fromHtml 应用 HTML 样式

java - 无法创建 Kafka Consumer

sql - 防止在 SQL 中使用十进制类型进行舍入

hibernate - DAO 和 Repository 模式有什么区别?