Есть ли проблема с объектами JPA, Oracle 10g и свойствами типа Календаря?
Вопрос
Я сталкиваюсь со следующим очень раздражающим поведением при использовании JPA entitys в сочетании с 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 со столбцом номера первичного ключа "ID" и столбцом МЕТКИ ВРЕМЕНИ "activationDate".
Предположим, я создаю экземпляр этого класса с датой активации "15.Сентябрь 2008, 00:00 утра".Мой местный часовой пояс - CEST, то есть GMT + 02:00.Когда я сохраняю этот объект и выбираю данные из таблицы T_ORDER с помощью sqlplus, я обнаруживаю, что в таблице на самом деле "14.Sep 2008 22:00" сохраняется, что пока нормально, потому что часовой пояс oracle db - GMT.
Но теперь самое неприятное.Когда я читаю эту сущность обратно в свою JAVA-программу, я обнаруживаю, что часовой пояс oracle игнорируется, и я получаю "14.Сентябрь 2008, 22:00 по восточному времени", что определенно неверно.
Таким образом, по сути, при записи в базу данных будет использоваться информация о часовом поясе, при чтении она будет проигнорирована.
Есть ли какое-нибудь решение для этого?Самым простым решением, я думаю, было бы установить для часового пояса oracle dbs значение GMT + 02, но, к сожалению, я не могу этого сделать, потому что есть другие приложения, использующие тот же сервер.
Мы используем следующую технологию
MyEclipse 6.5 JPA с гибернацией 3.2 Oracle 10g тонкий драйвер JDBC
Решение
Именно по этой причине вам не следует использовать Календарь для доступа к датам из базы данных.Вы должны использовать java.util.Date
как так:
@Temporal(TemporalType.TIMESTAMP)
@Column(name="activationDate")
public Date getActivationDate() {
return this.activationDate;
}
java.util.Date
указывает на определенный момент времени, независимо от каких-либо часовых поясов.Календарь можно использовать для форматирования даты для определенного часового пояса или региона.
Другие советы
У меня уже была своя доля проблем с JPA и временными метками.Я читал в форумы oracle и, пожалуйста, проверьте следующее:
- Поле в базе данных должно быть TIMESTAMP_TZ, а не просто TIMESTAMP
- Попробуйте добавить аннотацию @Temporal(значение = TemporalType.ВРЕМЕННАЯ МЕТКА)
- Если вам на самом деле не нужен часовой пояс, введите в поле дату или временную метку.