问题
I use Spring boot 1.4.2, which brings hibernate 5.0.11 (JPA 2.1).
I want to use the Java 8 time classes in my entities, and so included hibernate-java8
.
My entity defines a LocalDate field.
@Entity
@Table(name = "my_alarms_timeline", indexes = {...})
public class MyAlarm {
...
@Column(name = "validity_date")
@NotNull
private LocalDate validityDate;
}
I expect this to be mapped to a DATE in my H2 database.
In my DB I declare this as validity_date DATE NOT NULL,
.
When I try to run tests, I get the following error:
[INFO] Caused by: org.hibernate.tool.schema.spi.SchemaManagementException:
Schema-validation: wrong column type encountered in column [validity_date] in table [my_alarms_timeline];
found [date (Types#DATE)], but expecting [timestamp (Types#TIMESTAMP)]
To my surprise, if I change the DB definition to validity_date TIMESTAMP NOT NULL,
I get the error
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException:
Schema-validation: wrong column type encountered in column [validity_date] in table [my_alarms_timeline];
found [timestamp (Types#TIMESTAMP)], but expecting [date (Types#DATE)]
This is just the reverse message of the previous one.
I also tried, instead of including hibernate-java8
, to use an AttributeConverter<LocalDate, java.sql.Date>
but this produces the same error result.
What must I do, so that my LocalDate is mapped correctly to a DATE in the DB?
I also tried with a LocalDateTime
field mapped to a TIMESTAMP, and this works without problems...
回答1:
So I got it to run, by adding a columnDefinition="DATE"
to the @Column
annotation.
@Entity
@Table(name = "my_alarms_timeline", indexes = {...})
public class MyAlarm {
...
@Column(name = "validity_date", columnDefinition = "DATE")
@NotNull
private LocalDate validityDate;
}
Not sure why nobody else is seeing this issue...
回答2:
I've not used this in Spring but in "standard" JPA, I've done something like:
@Converter(autoApply = true)
public class OffsetDateTimeAttributeConverter implements AttributeConverter<OffsetDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(OffsetDateTime entityValue) {
if( entityValue == null )
return null;
return Timestamp.from(Instant.from(entityValue));
}
@Override
public OffsetDateTime convertToEntityAttribute(Timestamp databaseValue) {
if( databaseValue == null )
return null;
return OffsetDateTime.parse(databaseValue.toInstant().toString());
}
}
My table has "timestamp with timezone" columns. My @Entity then uses OffsetDateTime. You should be able to convert between your datatypes with something like this.
回答3:
I suspect that you have the following code somewhere in your project:
@EntityScan(basePackageClasses = { Application.class, Jsr310JpaConverters.class })
If you are using Hibernate 5.x you should remove the reference to Jsr310JpaConverters.class otherwise both Hibernate and Spring will attempt to handle Java 8 Date and Time objects. This can result in some very inconstant behaviour (such as LocalDate instances being persisted with the wrong value when running on machines that do not use UTC).
You should also remove any occurrences of:
@Column(columnDefinition = "DATE")
If you require it, it is a indication that something is seriously wrong with your hibernate configuration.
来源:https://stackoverflow.com/questions/40514341/java-8-localdate-in-hibernate-wrongly-mapped-to-timestamp