Поддержка JPA для Java 8 новых API даты и времени
Я использую Java 8 для своего нового проекта.
Я пытаюсь использовать новую дату и время api в java 8, но я не знаю, поддерживает ли JPA 2.1
этот новый API Date and Time или нет.
Пожалуйста, поделитесь своим опытом/мнением в поддержке JPA для новых API дат и времени в Java 8.
Могу ли я использовать новую дату и время api в Java 8 безопасно с JPA 2.1?
UPDATE:
Я использую Hibernate (4.3.5.Final) в качестве реализации JPA.
Ответы
Ответ 1
JPA 2.1 - это спецификация, появившаяся до Java 1.8, поэтому не требует никакой поддержки для нее. Очевидно, что некоторые реализации могут поддерживать некоторые функции Java 1.8. Некоторые из них имеют проблемы с байт-кодом Java 1.8 (например, EclipseLink). Я знаю, что DataNucleus поддерживает java.time и Java 1.8, так как тот, который я использую. Вам нужно будет проверить свою реализацию, каков ее уровень поддержки.
Было предложено, чтобы JPA 2.2 поддерживала типы java.time, см. эту проблему https://java.net/jira/browse/JPA_SPEC-63
Ответ 2
Для Hibernate 5.X просто добавьте
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<version>${hibernate.version}</version>
</dependency>
и
@NotNull
@Column(name = "date_time", nullable = false)
protected LocalDateTime dateTime;
будет работать без каких-либо дополнительных усилий.
См. https://hibernate.atlassian.net/browse/HHH-8844
UPDATE:
Пожалуйста, посмотрите на комментарий Джеффа Морина: поскольку Hibernate 5.2.x достаточно
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.1.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-...</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
См. https://github.com/hibernate/hibernate-orm/wiki/Migration-Guide---5.2 и
Интеграция Hibernate 5.2 с Spring каркасом 4.x
Ответ 3
Я использую Java 8, EclipseLink (JPA 2.1), PostgreSQL 9.3 и PostgreSQL Driver -Postgresql-9.2-1002.jdbc4.jar в моем проекте, и я могу использовать переменные LocalDateTime из нового API без проблем, но тип данных столбца является байтом в базе данных, поэтому вы можете прочитать его только из приложения Java, насколько мне известно. Вы можете использовать AttributeConverter для преобразования новых классов в java.sql.Date
Я нахожу этот код из Java.net
@Converter(autoApply = true)
public class LocalDatePersistenceConverter implements
AttributeConverter {
@Override
public java.sql.Date convertToDatabaseColumn(LocalDate entityValue) {
return java.sql.Date.valueOf(entityValue);
}
@Override
public LocalDate convertToEntityAttribute(java.sql.Date databaseValue) {
return databaseValue.toLocalDate();
}
Ответ 4
JPA 2.2 поддерживает java.time
JPA 2.2 теперь поддерживает LocalDate
, LocalTime
, LocalDateTime
, OffsetTime
и OffsetDateTime
.
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
Для реализации JPA 2.2 можно использовать Hibernate 5.2 или EclipseLink 2.7.
Hibernate 5 поддерживает больше типов java, чем JPA 2.2, например Duration
, Instant
и ZonedDateTime
.
Дополнительная информация:
Ответ 5
org.jadira.usertype можно использовать для сохранения API дат и времени JSR 310.
Проверьте этот примерный проект.
Из примера проекта
@MappedSuperclass
public class AbstractEntity {
@Id @GeneratedValue Long id;
@CreatedDate//
@Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime")//
ZonedDateTime createdDate;
@LastModifiedDate//
@Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime")//
ZonedDateTime modifiedDate;
}
Ответ 6
Я знаю, что это старый вопрос, но я подумал об альтернативном решении, которое может быть полезно.
Вместо того, чтобы сопоставлять новые классы java.time. * с существующими типами баз данных, вы можете использовать @Transient:
@Entity
public class Person {
private Long id;
private Timestamp createdTimestamp;
@Id
@GeneratedValue
public Long getId() { return id; }
private Timestamp getCreatedTimestamp() {
return createdTime;
}
private void setCreatedTimestamp(final Timestamp ts) {
this.createdTimestamp = ts;
}
@Transient
public LocalDateTime getCreatedDateTime() {
return createdTime.getLocalDateTime();
}
public void setCreatedDateTime(final LocalDateTime dt) {
this.createdTime = Timestamp.valueOf(dt);
}
}
Вы работаете с общедоступными методами getter/setter, которые используют новые классы даты и времени Java 8, но за кулисами геттер/сеттеры работают с устаревшими классами даты и времени. Когда вы сохраняете объект, устаревшее свойство date/time будет сохранено, но не новое свойство Java 8, поскольку оно аннотируется с @Transient.
Ответ 7
Для типа TIMESTAMP вы можете использовать этот конвертер:
@Converter(autoApply = true)
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime datetime) {
return datetime == null ? null : Timestamp.valueOf(datetime);
}
@Override
public LocalDateTime convertToEntityAttribute(Timestamp timestamp) {
return timestamp == null ? null : timestamp.toLocalDateTime();
}
}
Для типа DATE вы можете использовать этот конвертер:
@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {
@Override
public Date convertToDatabaseColumn(LocalDate date) {
return date == null ? null : Date.valueOf(date);
}
@Override
public LocalDate convertToEntityAttribute(Date date) {
return date == null ? null : date.toLocalDate();
}
}
Для типа ВРЕМЯ вы можете использовать этот конвертер:
@Converter(autoApply = true)
public class LocalTimeAttributeConverter implements AttributeConverter<LocalTime, Time> {
@Override
public Time convertToDatabaseColumn(LocalTime time) {
return time == null ? null : Time.valueOf(time);
}
@Override
public LocalTime convertToEntityAttribute(Time time) {
return time == null ? null : time.toLocalTime();
}
}
Ответ 8
Есть много способов сделать, и это зависит от вашей работы фрейма:
Если ваша рамочная работа имеет на поле Converter такой spring, выполните следующие действия:
1 -
@DateTimeFormat(pattern = "dd.MM.yyyy - HH:mm")
private Long createdDate;
здесь я использую формат устаревшей эпохи https://www.epochconverter.com/
эпоха очень гибкая и принятый формат
2- Другими способами является использование jpa @PostLoad @PreUpdate @PrePersist
@PostLoad
public void convert() {
this.jva8Date= LocalDate.now().plusDays(1);
}
или используйте темп один такой
@Transient
public LocalDateTime getCreatedDateTime() {
return createdTime.getLocalDateTime();
}