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.