I am developing a spring-boot project with MariaDB database.
I have a Student entity, which has a Exam property. In database, I would like to store the Exam property as a json field/column in student table.
The SQL for creating student table is:
CREATE TABLE IF NOT EXISTS student ( id bigint not null, exam json, first_name varchar(255), last_name varchar(255), primary key (id) ) engine=InnoDB; The Student entity class is:
@Data @NoArgsConstructor @AllArgsConstructor @Entity @TypeDefs({ @TypeDef(name = "json", typeClass = JsonStringType.class) }) public class Student implements Serializable { ... @Column(columnDefinition = "LONGTEXT") @Type(type = "json") private Exam exam; } Those annotations you see above are meant to store the exam property as a JSON field in student table.
The Exam class is not annotated as a JPA entity, but a normal class:
@Data @NoArgsConstructor @AllArgsConstructor public class Exam implements Serializable { private ZonedDateTime startTime; private String code; } As you see, the Exam has a ZonedDateTime property. My question later is about it.
I have also JpaRepository class:
@Repository public interface StudentRepository extends JpaRepository<Student, id> { } In my unit test code, I have a function to create a Student object:
public Student createStudentEntity() { // create exam, assign ZonedDateTime.now() to its "startTime" property Exam exam = new Exam(ZonedDateTime.now(), "math01"); Student student = new Student(); student.setExam(exam); ... return student; } Then, I call this function in my test to save the student to database:
@ActiveProfiles("test") @SpringBootTest class StudentTest { @Autowired StudentRepository studentRepo; @Test void test_save_student() { Student student = MyTestHelper.createStudentEntity(); studentRepo.saveStudent(student); // The assertion fails due to the "startTime" of "exam" json object mismatch Assertions.assertEquals(student, studentRepo.getStudentById(student.getId())); } The above test fails with message:
AssertionFailedError: expected: <Student(id=123,exam=Exam(startTime=2023-04-24T20:58:57.624489+03:00[Europe/Paris],...> but was: <Student(id=123,exam=Exam(startTime=2023-04-24T20:58:57.624489+03:00[UTC],...> So, the error in short tells the mismatch in timezone:
examjson value in created student isexam=Exam(startTime=2023-04-24T20:58:57.624489+03:00[Europe/Paris],- but when fetched from database, the fetched student contains
examjson with valueexam=Exam(startTime=2023-04-24T20:58:57.624489+03:00[UTC].
Why the fetched student from database has exam field contains startTime that is in [UTC] while before persisting it to database the same field in exam json is treated as [Europe/Paris]?
==== UPDATE ===
I tried @Mar-Z's answer, updated my Exam class (which is not a JPA entity) to:
@Data @NoArgsConstructor @AllArgsConstructor public class Exam implements Serializable { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSZ", timezone = "Europe/Paris") private ZonedDateTime startTime; private String code; } But it doesn't help, I still have the same issue: The fetched student from database having json field exam which contains the startTime part having [UTC] timezone.
examfield isjsonas indicated in my post. ThestartTimeis a property ofExamclass. So, I am persistingExamproperty ofStudentas ajson.