[JIRA] (HHH-16775) Hibernate interoperability with SQL Server is broken when useBulkCopyForBatchInsert=true
by Jakub Havlik (JIRA)
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=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100225- sha1:956085d )
2 years, 10 months