Подтвердить что ты не робот

Как сопоставить postgresql "метку времени с часовым поясом" в объекте JPA 2

У меня есть приложение JPA 2 (с Hibernate 3.6 в качестве реализации JPA), которое использует Postgresql (с драйвером JDBC 9.0-801.jdbc3).

У меня возникли проблемы с отображением полей "timestamp with time zone" в мои объекты JPA.

Вот пример:

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 )
)

Я попытался отобразить следующее:

@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 */

Я продолжаю получать исключение со следующей основной причиной: Caused by: org.hibernate.HibernateException: Wrong column type in public.backend_themetopic for column created. Found: timestamptz, expected: date

Что я пробовал

  • замена java.util.Calendar на java.util.Date - не имеет значения
  • с помощью java.sql.Timestamp - жаловался, что я не могу применить аннотацию @Temporal к Timestamp
  • с помощью org.joda.time.DateTime с пользовательской аннотацией @Type (@Type(type="org.joda.time.contrib.hibernate.PersistentDateTimeTZ")) также не работал

Ограничения

  • Это приложение взаимодействует с "устаревшей системой" - поэтому изменение типов полей даты не является хорошим вариантом.

Мой вопрос: как мне сопоставить эти временные метки, относящиеся к временному диапазону, в мои объекты JPA?

4b9b3361

Ответ 1

В конце концов я сделал эту "работу" - хакерским способом - отключив проверку схемы.

Раньше у меня был <property name="hibernate.hbm2ddl.auto" value="validate"/>"hibernate.hbm2ddl.auto" в моем persistence.xml. Когда я прокомментировал это свойство, начался мой сервер приложений, и модель "работала".

Конечная форма моего объекта:

@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 */

Прочитав немного по этому поводу, у меня сложилось впечатление, что нет простого способа сопоставить временную метку Postgresql с столбцами часовых поясов.

Некоторые реализации JPA + комбинации баз данных поддерживают это изначально (например, EclipseLink + Oracle). Для спящего режима с расширениями jodatime можно хранить временные метки, относящиеся к временной шкале, с использованием обычной временной метки + поля varchar для часового пояса (я не мог этого сделать, поскольку мне было запрещено изменять схему базы данных). Пользовательские типы Jadira или полностью пользовательские типы пользователей также могут быть использованы для решения этой проблемы.

Мне нужно отметить, что мой прецедент для этого объекта "только для чтения", поэтому я мог уйти с поистине наивным "решением".

Ответ 2

Добавить @Column(columnDefinition= "TIMESTAMP WITH TIME ZONE")

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