I recently upgraded my application to Spring Boot 3.1.4, Java 21, and Hibernate 6.2.9. Since the upgrade, I am encountering the following error when trying to save JSON data into my database:
WARN 1 — [erContainer#0-2] o.h.engine.jdbc.spi.SqlExceptionHelper
: SQL Error: 3144, SQLState: 22001
Data truncation: Cannot create a JSON value from a string with CHARACTER SET ‘binary’.
Here is the relevant code where the exception occurs:
@Service
public class JpaDataWritingServiceImpl implements DataWritingService {
@Autowired
TestDataRepository testDataRepository;
@Autowired
TestRepository testRepository;
@Override
public void writetestData(Long testId, String type, byte[] data, testStatus testStatus, boolean needsBackgroundtest) {
Optional<Test> maybeTest = testRepository.findById(testId);
if (maybeTest.isPresent()) {
Test test = maybeTest.get();
String metadata = generateMetadataForTestData(data);
TestData testData = new TestData(test, type, data, metadata);
LOG.debug("Saving TestData======> data={}, metadata={}", dataString, metadata); // To verify data before save() --> for
testDataRepository.save(new TestData(test, type, data, metadata)); // Fails here
} else {
LOG.warn("Didn't find testData with id {}", testId);
}
}
private String generateMetadataForTestData(byte[] data) {
String byteToStringData = new String(data, StandardCharsets.UTF_8);
JSONObject byteToString = new JSONObject(byteToStringData);
JSONObject stringToJson = new JSONObject();
if (byteToString.has("platform")) {
stringToJson.put("content_id", byteToString.getString("id"));
try {
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(byteToString.getString("timestamp"));
long epochTime = date.getTime() / 1000;
stringToJson.put("timestamp", epochTime);
} catch (ParseException e) {
LOG.error("DateTime parse exception: {}", e.getMessage());
}
}
return stringToJson.length() == 0 ? null : stringToJson.toString();
}
}
Error Stack Trace
Here is the error I am receiving:
Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement [Data truncation: Cannot create a JSON value from a string with CHARACTER SET ‘binary’.]
[insert into test_data (test_id, data, metadata, received_at, type) values (?,?,?,?,?)]
Entity Definition
Here is the CampaignData entity:
@Entity
@Table(name="test_data")
public class TestData {
public TestData(){}
public TestData(Test test,
String type,
byte[] data,
String metadata) {
this.test = test;
this.type = type;
this.data = data;
this.metadata = metadata;
this.receivedAt = Instant.now();
}
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne private Test test;
private String type;
@NotNull @Lob
private byte[] data;
@JsonIgnore
@OneToOne(cascade = CascadeType.ALL, mappedBy = "testData")
private TestDataTestStatus testStatus;
@Column(name = "received_at")
private Instant receivedAt;
@Lob
@Column(columnDefinition = "json")
private String metadata;
// Other fields and getters/setters...
}
Database Configuration:
CREATE TABLE `test_data` (
`id` bigint NOT NULL AUTO_INCREMENT,
`test_id` bigint NOT NULL,
`data` mediumblob NOT NULL,
`received_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`metadata` json DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_test_data_test` (`test_id`),
CONSTRAINT `fk_test_data_test` FOREIGN KEY (`test_id`) REFERENCES `test` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=175613200 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_as_ci
Observations
• The same code worked before the upgrade.
• The data field contains JSON data serialized as byte[], which I convert to String and store in the metadata column.
• The application log shows that data and metadata are valid JSON strings:
Saving testData======> data={"id":"113662220040053124", ...}, metadata={"content_id":"113662220040053124","timestamp":1734347839}
Questions
- Why am I getting a CHARACTER SET ‘binary’ error when saving the JSON metadata or byte[] data now?
- Is there a new requirement in Hibernate 6.2.x or Spring Boot 3.1.x for handling JSON or byte[] fields?