J'ai une application JPA 2 (avec Hibernate 3.6 comme implémentation JPA) qui utilise Postgresql (avec le pilote JDBC 9.0-801.jdbc3).
J'ai du mal à mapper les champs "horodatage avec fuseau horaire" dans mes entités JPA.
Voici un exemple:
CREATE TABLE theme
(
id serial NOT NULL,
# Fields that are not material to the question have been edited out
run_from timestamp with time zone NOT NULL,
run_to timestamp with time zone NOT NULL,
CONSTRAINT theme_pkey PRIMARY KEY (id ),
CONSTRAINT theme_name_key UNIQUE (name )
)
J'ai essayé de mapper comme suit:
@Entity
@Table(schema = "content", name = "theme")
public class Theme extends AbstractBaseEntity {
private static final long serialVersionUID = 1L;
@Column(name = "run_from")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runFrom;
@Column(name = "run_to")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runTo;
/* The rest of the entity has been edited out */
Je continue d'obtenir une exception avec la cause racine suivante: Caused by: org.hibernate.HibernateException: Wrong column type in public.backend_themetopic for column created. Found: timestamptz, expected: date
Ce que j'ai essayé
Java.util.Calendar
par Java.util.Date
- n'a fait aucune différenceJava.sql.Timestamp
- s'est plaint que je ne pouvais pas appliquer l'annotation @Temporal
à un Timestamp
org.joda.time.DateTime
avec une annotation @Type
personnalisée (@Type(type="org.joda.time.contrib.hibernate.PersistentDateTimeTZ")
) ne fonctionnait pas non plusContraintes
Ma question est: comment dois-je mapper ces horodatages sensibles au fuseau horaire dans mes entités JPA?
J'ai finalement fait ce "travail" - d'une manière hackish - en désactivant la validation du schéma.
Auparavant, j'avais <property name="hibernate.hbm2ddl.auto" value="validate"/>"hibernate.hbm2ddl.auto"
dans mon persistence.xml. Lorsque j'ai commenté cette propriété, mon serveur d'applications a démarré et le modèle a "fonctionné".
La forme finale de mon entité était:
@Entity
@Table(schema = "content", name = "theme")
public class Theme extends AbstractBaseEntity {
private static final long serialVersionUID = 1L;
@Column(name = "run_from", columnDefinition = "timestamp with time zone not null")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runFrom;
@Column(name = "run_to", columnDefinition = "timestampt with time zone not null")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runTo;
/* Getters, setters, .hashCode(), .equals() etc omitted */
Après avoir lu pas mal de choses à ce sujet, j'ai eu l'impression qu'il n'y a pas de moyen facile de mapper l'horodatage Postgresql avec des colonnes de fuseau horaire.
Certaines combinaisons d'implémentation JPA + de base de données prennent en charge cela nativement (EclipseLink + Oracle en est un exemple). Pour la mise en veille prolongée, avec des extensions Jodatime, il est possible de stocker des horodatages sensibles au fuseau horaire en utilisant un horodatage normal + un champ varchar pour le fuseau horaire (je ne pouvais pas le faire car j'étais contraint de modifier le schéma de la base de données). types d'utilisateurs Jadira ou des types d'utilisateurs entièrement personnalisés peuvent également être utilisés pour résoudre ce problème.
Je dois noter que mon cas d'utilisation pour cette entité est "en lecture seule", donc je pourrais m'en tirer avec une "solution" apparemment naïve.
Ajouter @Column(columnDefinition= "TIMESTAMP WITH TIME ZONE")
@Column(name = "run_from", columnDefinition= "TIMESTAMP WITH TIME ZONE")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runFrom;