Rod*_*eas 8 spring hibernate spring-data-jpa
我有一个奇怪的问题,我不知道为什么会发生。我敢肯定我做错了,因为这是我第一次使用数据投影,而使用DTO从来没有这样的问题。
我几乎有一个SELECT政治家,正在返回各种数据类型的某些列。我有一个接口要传递给JPA存储库,以便它可以进行接口映射。但是,它不是根据列名(例如'accountnum'-> getAccountnumber())映射结果,而是按字母顺序映射列。因此,如果“ date_of_order”是SELECT语句中的第一个,则其值将由返回getAccountnumber()。
我有一个预计的界面,看起来像这样:
public interface FlatSearchResult {
String getAccountnumber();
UUID getTrackingId;
Date getDateOfOrder;
}
Run Code Online (Sandbox Code Playgroud)
我的模型有三个这样的表:
ACCOUNT
- account_id : uuid (pkey)
- accountnumber : string
ORDERS
- order_id : uuid (pkey)
- date_of_order : timestamp
- account_id : uuid (fkey)
TRACKING
- tracking_id : uuid (pkey)
- order_id : uuid (fkey)
Run Code Online (Sandbox Code Playgroud)
这些表中的每个都有其他列,但是它们并不相关。
我有一个使用简单查询定义的存储库:
public interface OrderTrackingRepository extends JpaRepository<Account, UUID> {
@Query( nativeQuery = true,
value = "SELECT o.date_of_order, a.accountnumber, t.tracking_id " +
"FROM account as a " +
"INNER JOIN orders as o USING (account_id) " +
"INNER JOIN tracking as t USING (tracking_id) " +
"WHERE a.accountnumber = :acctnum")
<T> Collection<T> findOrderInfoForAccount(@Param("acctnum") acctNumber, Class<T> type);
}
Run Code Online (Sandbox Code Playgroud)
当我调用此方法时,查询将返回正确的行。但是,它不是使用列名进行映射(例如getDateOfOrder(),将date_of_order 映射到),而是根据SELECT语句中列的顺序映射到接口中按字母顺序排序的方法。
所以:
SELECT date_of_order, accountnumber, tracking_id
Run Code Online (Sandbox Code Playgroud)
结果是:
getAccountNumber() -> date_of_order
getDateOfOrder() -> accountnumber
getTrackingId() -> tracking_id
Run Code Online (Sandbox Code Playgroud)
它会以这种方式持续返回,因此这不是暂时的问题。
作为临时的解决方法,我对SELECT语句中的列进行了重新排序。但是我宁愿不必这样做,因为这就像遍历结果集并依赖列位置一样,这让我有些抽搐。
如何获得Spring JPA将结果集映射到我的界面?我是否需要在投影接口的方法上添加注释,以告诉Spring它指的是什么列名?
我的数据库是Postgres。我正在使用Spring 5.0.2.RELEASE和Spring-Boot 2.0.0.M7。如果需要,我可以将其中任何一个调整为较新的版本,但没有较旧的版本。我正在使用C3P0 0.9.5.2进行连接缓冲,并使用postgres-9.2-1002.jdbc4。这个版本的Spring-Boot引入了我所有其他依赖项(休眠等)。
我遇到了同样的问题,我通过按字母顺序对查询列进行排序来解决。
在你的情况下:
public interface OrderTrackingRepository extends JpaRepository<Account, UUID> {
@Query( nativeQuery = true,
value = "SELECT a.accountnumber, o.date_of_order, t.tracking_id " +
"FROM account as a " +
"INNER JOIN orders as o USING (account_id) " +
"INNER JOIN tracking as t USING (tracking_id) " +
"WHERE a.accountnumber = :acctnum")
<T> Collection<T> findOrderInfoForAccount(@Param("acctnum") acctNumber, Class<T> type);
}
Run Code Online (Sandbox Code Playgroud)
所以你会得到:
getAccountNumber() -> accountnumber getDateOfOrder() -> date_of_order getTrackingId() -> tracking_id
不确定这是否是正确的解决方案,因为它仅适合描述的80%。但是评论太久了。所以我们开始。
我认为您误解了@osamayaccoub或文档。您的财产名称可以。但是您选择的列应匹配Java约定。
因此,首先要解决的问题是
value = "SELECT o.date_of_order as dateOfOrder, a.accountnumber as accountNumber, t.tracking_id as trackingId "
Run Code Online (Sandbox Code Playgroud)
注意:这实际上可能有效,但可能会在以后中断,因此即使确实有效,也请继续阅读
但是Postgres会将所有未用双引号引起来的内容转换为小写(Oracle和MySql做类似的事情,尽管细节有所不同,尚不了解其他DB)。因此,您确实应该使用:
value = "SELECT o.date_of_order as \"dateOfOrder\", a.accountnumber as \"accountNumber\", t.tracking_id as \"trackingId\" "
Run Code Online (Sandbox Code Playgroud)
这可能不起作用,因为您使用的Hibernate版本存在一个错误,该错误会将所有内容都转换为小写。
因此,您应该升级到最新的Hibernate版本5.3.13,此版本已修复该问题。
有趣的是,此错误修复可能会破坏没有双引号的版本。但是,对于此Spring Data JPA问题,它应该可以与此PR再次配合使用。
我不明白的部分是,为什么要使用列顺序分配东西。
| 归档时间: |
|
| 查看次数: |
6751 次 |
| 最近记录: |