Есть ли проблема с объектами JPA, свойствами Oracle 10g и типами календаря?

Я испытываю следующее очень раздражающее поведение при использовании сущностей JPA в сочетании с Oracle 10g.

Предположим, что у вас есть следующая сущность.

@Entity
@Table(name = "T_Order")
public class TOrder implements Serializable {
    private static final long serialVersionUID = 2235742302377173533L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "activationDate")
    private Calendar activationDate;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Calendar getActivationDate() {
        return activationDate;
    }

    public void setActivationDate(Calendar activationDate) {
        this.activationDate = activationDate;
    }
}

Этот объект сопоставляется с Oracle 10g, поэтому в БД будет таблица T_ORDER с номером первичного ключа NUMBER "ID" и столбцом TIMESTAMP "activationDate".

Предположим, что я создаю экземпляр этого класса с датой активации "15. Sep 2008 00:00 AM". Мой часовой пояс - CEST, GMT + 02: 00. Когда я сохраняю этот объект и выбираю данные из таблицы T_ORDER с помощью sqlplus, я обнаруживаю, что в таблице фактически "14. Sep 2008 22:00" сохраняется, что пока нормально, потому что часовой пояс oracle db - GMT.

Но теперь раздражающая часть. Когда я прочитал этот объект обратно в свою программу JAVA, я узнаю, что часовой пояс оракула игнорируется, и я получаю "14. сент. 2008 22:00 CEST", что совершенно неверно.

В принципе, при записи в БД будет использоваться информация о часовом поясе, при чтении она будет проигнорирована.

Есть ли какое-либо решение для этого? Самое простое решение, по-моему, было бы установить часовой пояс oracle dbs на GMT + 02, но, к сожалению, я не могу этого сделать, потому что есть другие приложения, использующие один и тот же сервер.

Мы используем следующую технологию

MyEclipse 6.5 JPA с Hibernate 3.2 Драйвер JDBC Oracle 10g

Ответ 1

Вы не должны использовать Календарь для доступа к датам из базы данных по этой точной причине. Вы должны использовать java.util.Date так:

@Temporal(TemporalType.TIMESTAMP)
@Column(name="activationDate")
public Date getActivationDate() {
    return this.activationDate;
}

java.util.Date указывает на момент времени, независимо от любых временных зон. Календарь можно использовать для форматирования даты определенного часового пояса или локали.

Ответ 2

У меня уже была своя доля проблем с JPA и метками времени. Я читал в oracle forums и, пожалуйста, проверьте следующее:

  • Поле в базе данных должно быть TIMESTAMP_TZ, а не только TIMESTAMP
  • Попробуйте добавить аннотацию @Temporal (value = TemporalType.TIMESTAMP)
  • Если вам действительно не нужен часовой пояс, введите поле даты или времени.