I use spring-data-jdbc to store and retrieve data from the underlying repository.
I have a date-time field that has to be stored with hour, minutes and seconds.
So in my entity the field is declared as LocalDateTime.
My understanding is that the framework converts my LocalDateTime to a java.sql.Date, so the precision is lost during the insertion in the database.
I use ListCrudRepository<AuditLogEntity,Long>
to store and retrieve the records.
After multiple searches on the web, I didn't find any article, tutorial related to my problem.
What I tried is to replace my LocalDateTime by Timestamp.
Here is my entity:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table("AUDIT_LOG")
public class AuditLogEntity {
@Id
private Long id;
@Column("USER_ID")
private String userId;
@Column("ACTION_ORIGIN")
private String actionOrigin;
@Column("ACTION_NAME")
private String actionName;
@Column("ACTION_DATE")
private Timestamp actionDate;
@Column("REFERENCE")
private String reference;
@Column("ACTION_BODY")
private String actionBody;
public static AuditLogEntity create(AuditLogCreation auditLogCreation) {
return new AuditLogEntity(null,
auditLogCreation.getUserId(),
auditLogCreation.getActionOrigin(),
auditLogCreation.getActionName(),
Timestamp.valueOf(auditLogCreation.getActionDate()),
auditLogCreation.getReference(),
auditLogCreation.getActionBody());
}
public static AuditLog toModel(AuditLogEntity entity) {
return new AuditLog(entity.getUserId(),
entity.getActionName(),
entity.getActionOrigin(),
entity.getActionDate().toLocalDateTime(),
entity.getReference(),
entity.getActionBody());
}
Here is my repository:
@Component
public class AuditLogRepositoryImpl implements AuditLogRepository {
private final JdbcAuditLogRepository jdbcAuditLogRepository;
public AuditLogRepositoryImpl(JdbcAuditLogRepository jdbcAuditLogRepository) {
this.jdbcAuditLogRepository = jdbcAuditLogRepository;
}
@Override
public AuditLog create(AuditLogCreation auditLogCreation) {
AuditLogEntity auditLogEntity = AuditLogEntity.create(auditLogCreation);
AuditLogEntity save = this.jdbcAuditLogRepository.save(auditLogEntity);
return AuditLogEntity.toModel(save);
}
@Override
public List<AuditLog> findAll() {
List<AuditLogEntity> all = this.jdbcAuditLogRepository.findAll();
return all
.stream()
.map(AuditLogEntity::toModel)
.toList();
}
}
The ListCrudRepository:
@Repository
public interface JdbcAuditLogRepository extends ListCrudRepository<AuditLogEntity, Long> {
}
My test:
@SpringBootTest
@ActiveProfiles("integration")
class AuditLogRepositoryImplIntegrationTest {
@Inject
private AuditLogRepository auditLogRepository;
@Test
void test() {
LocalDateTime expected = LocalDateTime.of(LocalDate.of(2020, 4, 30), LocalTime.of(3, 26, 50));
AuditLogCreation auditLogCreation = AuditLogCreation.builder()
.userId("UserId")
.reference("Reference")
.actionName("Action Name")
.actionOrigin("Action origin")
.actionDate(expected)
.actionBody("Action Body")
.build();
this.auditLogRepository.create(auditLogCreation);
List<AuditLog> all = this.auditLogRepository.findAll();
AuditLog auditLog = all.get(0);
assertThat(auditLog.getActionDate()).isEqualTo(expected);
}
}
And the result:
org.opentest4j.AssertionFailedError:
expected: 2020-04-30T03:26:50 (java.time.LocalDateTime)
but was: 2020-04-30T00:00 (java.time.LocalDateTime)
when comparing values using 'ChronoLocalDateTime.timeLineOrder()'
Expected :2020-04-30T03:26:50 (java.time.LocalDateTime)
Actual :2020-04-30T00:00 (java.time.LocalDateTime)
If I check the following topic: Spring-data-jdbc microsecond precision lost during insert of LocalDateTime type variable It seems he succeeds in storing the date with a precision of the milliseconds whilst on my side only the date without hh:MM:ss is stored.
So I'm a bit lost. Am I missing something?
Thanks for your help.