Jakub Havlik (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5a6759f...
) *created* an issue
Hibernate ORM (
https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiMGNmZDQ1MGQ0...
) / Bug (
https://hibernate.atlassian.net/browse/HHH-16775?atlOrigin=eyJpIjoiMGNmZD...
) HHH-16775 (
https://hibernate.atlassian.net/browse/HHH-16775?atlOrigin=eyJpIjoiMGNmZD...
) Hibernate interoperability with SQL Server is broken when useBulkCopyForBatchInsert=true
(
https://hibernate.atlassian.net/browse/HHH-16775?atlOrigin=eyJpIjoiMGNmZD...
)
Issue Type: Bug Affects Versions: 6.1.7 Assignee: Unassigned Attachments:
image-20230609-165335.png, image-20230609-165704.png Components: hibernate-core Created:
09/Jun/2023 10:11 AM Environment: Spring Boot 3.0.5 with default versions of
dependencies:
Hibernate 6.1.7
com.microsoft.sqlserver:mssql-jdbc:11.2.3
JVM 17 Labels: sqlserver Priority: Major Reporter: Jakub Havlik (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5a6759f...
)
As far as I understand Hibernate is generating INSERT string in a method:
org.hibernate.persister.entity.AbstractEntityPersister::generateInsertString
SQL Server JDBC driver is preparing column metadata in:
com.microsoft.sqlserver.jdbc.SQLServerBulkBatchInsertRecord::addColumnMetadataInternal
And calls it in com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement::executeBatch when
trying to perform BULK INSERT :
Problem is that method
com.microsoft.sqlserver.jdbc.SQLServerBulkBatchInsertRecord::getRowData is creating BULK
INSERT statement by mapping column metadata to Hibernate query by index of the fields and
not by names. But as the order of both libraries is inconsistent it doesn’t find anything
returns mostly nulls:
(
https://hibernate.atlassian.net/rest/api/3/attachment/content/50435 )
(This picture is the most important point of this bug)
Process than crashes with Caused by: java.sql.BatchUpdateException: Cannot insert the
value NULL into column 'XXX', table 'YYY'; column does not allow nulls.
INSERT fails.
Full stack-trace starting in our code when flush is called:
getRowData:260, SQLServerBulkBatchInsertRecord (com.microsoft.sqlserver.jdbc)
writeBatchData:3649, SQLServerBulkCopy (com.microsoft.sqlserver.jdbc)
doInsertBulk:1574, SQLServerBulkCopy (com.microsoft.sqlserver.jdbc)
doExecute:671, SQLServerBulkCopy$1InsertBulk (com.microsoft.sqlserver.jdbc)
execute:7620, TDSCommand (com.microsoft.sqlserver.jdbc)
executeCommand:3916, SQLServerConnection (com.microsoft.sqlserver.jdbc)
sendBulkLoadBCP:705, SQLServerBulkCopy (com.microsoft.sqlserver.jdbc)
writeToServer:1662, SQLServerBulkCopy (com.microsoft.sqlserver.jdbc)
writeToServer:628, SQLServerBulkCopy (com.microsoft.sqlserver.jdbc)
executeBatch:2124, SQLServerPreparedStatement (com.microsoft.sqlserver.jdbc)
executeBatch:127, ProxyStatement (com.zaxxer.hikari.pool)
executeBatch:-1, HikariProxyPreparedStatement (com.zaxxer.hikari.pool)
performExecution:123, BatchingBatch (org.hibernate.engine.jdbc.batch.internal)
addToBatch:92, BatchingBatch (org.hibernate.engine.jdbc.batch.internal)
insert:3438, AbstractEntityPersister (org.hibernate.persister.entity)
insert:4073, AbstractEntityPersister (org.hibernate.persister.entity)
execute:103, EntityInsertAction (org.hibernate.action.internal)
executeActions:612, ActionQueue (org.hibernate.engine.spi)
lambda$executeActions$1:483, ActionQueue (org.hibernate.engine.spi)
accept:-1, ActionQueue$$Lambda$1955/0x00000008016bc200 (org.hibernate.engine.spi)
forEach:721, LinkedHashMap (java.util)
executeActions:480, ActionQueue (org.hibernate.engine.spi)
performExecutions:329, AbstractFlushingEventListener (org.hibernate.event.internal)
onFlush:39, DefaultFlushEventListener (org.hibernate.event.internal)
accept:-1, SessionImpl$$Lambda$1949/0x0000000801975da0 (org.hibernate.internal)
fireEventOnEachListener:107, EventListenerGroupImpl
(org.hibernate.event.service.internal)
doFlush:1425, SessionImpl (org.hibernate.internal)
flush:1411, SessionImpl (org.hibernate.internal)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:77, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:568, Method (java.lang.reflect)
invoke:311, SharedEntityManagerCreator$SharedEntityManagerInvocationHandler
(org.springframework.orm.jpa)
flush:-1, $Proxy202 (jdk.proxy2)
...
Expectation: As AbstractEntityPersister already contains comments and code specially
preparing statements for Oracle as there are comments like this:
// HHH-4635
// Oracle expects all Lob properties to be last in inserts
// and updates. Insert them at the end.
I’d expect Hibernate to be able to also prepare query which is usable by SQL Server when
using BULK INSERT
(
https://hibernate.atlassian.net/browse/HHH-16775#add-comment?atlOrigin=ey...
) Add Comment (
https://hibernate.atlassian.net/browse/HHH-16775#add-comment?atlOrigin=ey...
)
Get Jira notifications on your phone! Download the Jira Cloud app for Android (
https://play.google.com/store/apps/details?id=com.atlassian.android.jira....
) or iOS (
https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=Em...
) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100225- sha1:956085d )