SQL Server JDBC driver converting strings to byte array references during insert

I’m working with Java 17, Spring Boot 3.3, and SQL Server JDBC driver version 12.10.0.jre11. I’ve run into a weird issue where my string values are being saved as byte array object references instead of actual strings.

Here’s what’s happening:

  • Database column: [RegionCode] nvarchar NOT NULL
  • Java value I’m passing: “CA”
  • What gets stored in database: “[B@7f31245a”
final var hibernateSession = entityManager.unwrap(Session.class);
hibernateSession.doWork(conn -> {
    try (PreparedStatement stmt = conn.prepareStatement("insert into regions (RegionCode) values (?)")) {
        for (T item : records) {
            stmt.setString(1, item.getRegion());
            stmt.addBatch();
        }
        stmt.executeBatch();
    }
});

When I debug the PreparedStatement, the first parameter shows up as AppDTVImpl with jdbcType=VARCHAR, but the value is showing as a byte array with javaType=BYTEARRAY.

I also tried being more explicit with the type but it didn’t work:

stmt.setObject(1, item.getRegion(), Types.VARCHAR);

UPDATE: Found the fix

Turns out the problem was caused by this setting:

dataSource.setUseBulkCopyForBatchInsert(true);

This might be related to having an identity column in my table. The bulk copy API seems to have some issues with string handling. Disabling this fixed the problem, though I wish the JDBC driver handled this more gracefully.

I hit this same issue about a year ago. The SQL Server JDBC driver binds parameters differently when bulk copy is on - it serializes them in a way that treats strings like byte arrays internally. This gets messy with mixed column types, especially identity columns like you found. Honestly, the performance hit from turning off bulk copy isn’t bad unless you’re pushing thousands of records at once. For most apps, having strings work properly is worth the small speed trade-off.

yeah, that’s a known issue with the mssql jdbc driver during bulk copy operations. the driver switches to treating all parameters as binary data instead of handling them properly. really frustrating that it fails silently without any warnings - just corrupts your data. nice work tracking down the root cause tho!

Wow, that’s really interesting! Never seen the bulk copy setting mess with string encoding like that. Wonder if it hits other data types too or just strings? Did you notice any performance changes after turning off useBulkCopyForBatchInsert?