Classes as LocalDateTime
from the package java.time
are value based classes. If I have an entity using such an object as a field I run into the following "problem":
Value based classes shouldn't be serialized. However, the JPA entity has to implement the interface Serializable. What is the solution for that paradox? Shouldn't someone use LocalDateTime as a field of an JPA entity? Use Date instead? This would be unsatisfying.
This problem is a Sonar rule squid:S3437
and therefore there are a lot of bugs in the project, since we changed from Date to LocalDateTime ...
Non compliant solution due to value based class usage:
@Entity
public class MyEntity implements Serializable{
@Column
private String id; // This is fine
@Column
private LocalDateTime updated; // This is not ok, as LocalDateTime is a value based class
@Column
private Date created; // This however is fine..
}
My answer could seem quite direct and valueless, but it is more for getting things together and to summarise.
First thing, it that there is no "golden bullet" solution of this problem. Something definitely has to be changed and I see 3 options or 3 alternatives:
Remove Serializable
interface. It is not a "good practice" to put Serializable
on all entities. It is needed only if you are going to use instances of it as detached objects: When and why JPA entities should implement Serializable interface?.
Use Timestamp type instead of LocalDateTime. It seems to me that it is equivalent:
https://github.com/javaee/jpa-spec/issues/63
Instant, LocalDateTime, OffsetDateTime, and ZonedDateTime map as timestamp values by default. You may mark a property of one of these types with @TeMPOraL to specify a different strategy for persisting that property.
@SuppressWarnings("squid:S3437")
.I don't quite understand what you DB accepts from jpa. When I deal with Postgres, I use a customized converter:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.sql.Timestamp;
import java.time.LocalDateTime;
@Converter(autoApply = true)
public class LocalDateTimePersistenceConverter implements AttributeConverter<LocalDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime locDateTime) {
return (locDateTime == null ? null : Timestamp.valueOf(locDateTime));
}
@Override
public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
}
}
And I use it this way:
@Column(name = "create_date")
@Convert(converter = LocalDateTimePersistenceConverter.class)
private LocalDateTime createDate;
You see, here I convert LocalDateTime to Timestamp (accepted by postgres) and back.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With