选择多个列并将其设置为 DTO 列表

Posted

技术标签:

【中文标题】选择多个列并将其设置为 DTO 列表【英文标题】:Selecting multiple columns and set it to list of DTOs 【发布时间】:2016-03-26 02:57:06 【问题描述】:

我想在单个查询中从数据库中获取多个列,并将其设置为相应的 DTO 对象字段。

错误信息:

java.lang.IllegalStateException: No data type for node:
org.hibernate.hql.internal.ast.tree.IdentNode
 +-[IDENT] IdentNode: 'payment' originalText=payment

查询:

TypedQuery<Object[]> query = entityManager.createQuery("SELECT
payment, createdOn,responseMessage FROM PaymentLog log WHERE log.id
=:personId", Object[].class);

query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<Object[]> results =  query.getResultList();

for (Object[] log : results) 
   paymentTransaction.setAmount(log[0].toString());
   paymentTransaction.setDate(log[1].toString());
   paymentTransaction.setDescription(log[2].toString());
   transactionList.add(paymentTransaction);

附:我知道我可以使用 JPA 构造函数表达式。但是由于我必须在 DTO 列表中添加 DTO(即 transactionList),所以有没有一种 JPA 构造表达式的方法,我可以通过只运行一次查询而不是在每个 DTO 的循环中来做到这一点?

【问题讨论】:

当您不发布此处使用的实体时,谁能说查询是否有任何“错误”?我没有水晶球,但也许其他人有 【参考方案1】:

您可以让 JPA 提供程序通过构造函数表达式为您转换结果集:

http://www.objectdb.com/java/jpa/query/jpql/select#Result_Classes_Constructor_Expressions_

https://en.wikibooks.org/wiki/Java_Persistence/JPQL#Constructors

这要求指定的类有一个与选择表达式匹配的构造函数。这将如下所示:

TypedQuery<PaymentTransaction> query = entityManager.createQuery("SELECT new PaymentTransaction (log.payment, log.createdOn, log.responseMessage ) FROM PaymentLog log WHERE log.id
=:personId", PaymentTransaction.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentTransaction> results =  query.getResultList();

在 JPA 2.1 中,您也可以像下面这样:

https://en.wikibooks.org/wiki/Java_Persistence/Querying#ConstructorResult_.28JPA_2.1.29

【讨论】:

【参考方案2】:

你可以做的是:

TypedQuery<PaymentLog> query = entityManager.createQuery("SELECT log FROM PaymentLog log WHERE log.id =:personId", PaymentLog.class);

query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentLog> results =  query.getResultList();

for (PaymentLog log : results) 
   paymentTransaction.setAmount(log.getPayment());
   paymentTransaction.setDate(log.getCreatedOn());
   paymentTransaction.setDescription(log.getResponseMessage());
   transactionList.add(paymentTransaction);

如果您不打算使用数据库,那么从数据库中选择所有内容并不是一个好主意。如果所选字段是表中唯一的列,则上述方法有效。

如果表中有更多的列,前一个仍然可以工作,但这可能会更好:

TypedQuery<PaymentTransaction> query = entityManager.createQuery("SELECT new PaymentTransaction (log.payment, log.createdOn, log.responseMessage) FROM PaymentLog log WHERE log.id =:personId", PaymentTransaction.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentTransaction> results =  query.getResultList();

上述查询将返回已创建的 PaymentTransactions 列表。您必须注意,PaymentTransaction 类应该有一个以给定顺序接受这些字段的构造函数。否则会引发异常

【讨论】:

以上是关于选择多个列并将其设置为 DTO 列表的主要内容,如果未能解决你的问题,请参考以下文章

delphi中如何设置DBGridEH第一列为下拉列,并使其控制表格筛选

如何从下拉列表中选择多个项目并将多个值插入 MYSQL

具有不同查询选择列表的广义 DTO 填充方法

允许在 Rhandsontable 列下拉列表中进行多选

用于从实体类及其导航属性中选择多个列的 Linq Lambda 表达式

如何设置 select2 下拉菜单的最小宽度和最大宽度?