web-dev-qa-db-fra.com

Comment mapper "timestamp with time zone" postgresql dans une entité JPA 2

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é

  • remplacer Java.util.Calendar par Java.util.Date - n'a fait aucune différence
  • utilisant Java.sql.Timestamp - s'est plaint que je ne pouvais pas appliquer l'annotation @Temporal à un Timestamp
  • l'utilisation de org.joda.time.DateTime avec une annotation @Type personnalisée (@Type(type="org.joda.time.contrib.hibernate.PersistentDateTimeTZ")) ne fonctionnait pas non plus

Contraintes

  • Cette application interagit avec un "système hérité" - donc, changer les types des champs de date n'est pas une bonne option

Ma question est: comment dois-je mapper ces horodatages sensibles au fuseau horaire dans mes entités JPA?

29
Ngure Nyaga

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.

9
Ngure Nyaga

Ajouter @Column(columnDefinition= "TIMESTAMP WITH TIME ZONE")

@Column(name = "run_from", columnDefinition= "TIMESTAMP WITH TIME ZONE")
@NotNull
@Temporal(TemporalType.TIMESTAMP)
private Date runFrom;
7
Alexei Osipov