给定一个 postgresql 表
Table "public.test"
Column | Type | Modifiers
----------+-----------------------------+-----------
id | integer | not null
info | text |
以及以下值:
# select * from test;
id | info
----+--------------
3 | value3
4 | value4
5 | value5
您可能知道使用 postgresql,您可以使用这种语句来更新具有不同值的多行:
update test set info=tmp.info from (values (3,'newvalue3'),(4,'newvalue4'),(5,'newvalue5')) as tmp (id,info) where test.id=tmp.id;
它导致表在单个查询中更新为:
# select * from test;
id | info
----+--------------
3 | newvalue3
4 | newvalue4
5 | newvalue5
我一直在四处寻找如何让hibernate为更新查询生成这种语句。我知道如何使它适用于插入查询(使用 reWriteBatchedInserts jdbc 选项和休眠批处理配置选项)。
但是是否可以进行更新查询或者我必须自己编写本机查询?无论我做什么,hibernate 总是向数据库发送单独的更新查询(我正在查看 postgresql 服务器语句日志以获得此确认)。
2020-06-18 08:19:48.895 UTC [1642] LOG: execute S_6: BEGIN
2020-06-18 08:19:48.895 UTC [1642] LOG: execute S_8: update test set info = $1 where id = $2
2020-06-18 08:19:48.895 UTC [1642] DETAIL: parameters: $1 = 'newvalue3', $2 = '3'
2020-06-18 08:19:48.896 UTC [1642] LOG: execute S_8: update test set info = $1 where id = $2
2020-06-18 08:19:48.896 UTC [1642] DETAIL: parameters: $1 = 'newvalue4', $2 = '4'
2020-06-18 08:19:48.896 UTC [1642] LOG: execute S_8: update test set info = $1 where id = $2
2020-06-18 08:19:48.896 UTC [1642] DETAIL: parameters: $1 = 'newvalue4', $2 = '5'
2020-06-18 08:19:48.896 UTC [1642] LOG: execute S_1: COMMIT
我总是发现发出单个大规模更新查询比针对单行的许多单独更新快很多倍。对于许多单独的更新查询,即使它们是由 jdbc 驱动程序批量发送的,它们仍然需要由服务器顺序处理,因此它不如针对多行的单个更新查询效率高。因此,如果有人有一个不涉及为我的实体编写本机查询的解决方案,我将非常高兴!
更新
为了进一步完善我的问题,我想补充说明。我正在寻找一种不会放弃 Hibernate 脏检查功能以进行实体更新的解决方案。对于必须更新实体列表上具有不同值的几个基本字段的一般情况,我试图避免手动编写批量更新查询。我目前正在研究休眠的 SPI,看看它是否可行。 org.hibernate.engine.jdbc.batch.spi.Batch
似乎是合适的地方,但我还不太确定,因为我从未对休眠 SPI 做过任何事情)。欢迎任何见解!