如何在 Oracle 中使用 JPA 存储日期和时间?
Posted
技术标签:
【中文标题】如何在 Oracle 中使用 JPA 存储日期和时间?【英文标题】:how to store date AND time with JPA in Oracle? 【发布时间】:2012-06-04 21:35:04 【问题描述】:我正在使用 WebSphere 7 (Java EE 5) 和 OpenJPA 1.2.1。
我有一个带有“modifiedTimestamp
”属性的 JPA 对象,如下所示:
@Entity
public class Widget
/* ... */
private java.sql.Date modifiedTimestamp;
/* ... */
Oracle 数据库中相关字段的类型为DATE
。
我是这样设置日期的......
myWidget.setModifiedTimestamp(new java.sql.Data(System.currentTimeMillis());
...它被存储了,但是当我读回它时,一天中的时间还没有被存储,它允许返回为 24:00。
这是 JPA 的事情,还是 Oracle 的事情?任何建议都非常感谢!
谢谢
【问题讨论】:
好问题——我正在使用 WebSphere 7 (Java EE 5) 和 OpenJPA 1.2.1。 java.sql.Date 根据其 javadocs 仅存储日期。也许你想要 java.util.Date? 查看***.com/questions/2188768/… 了解休眠,我想你可以试试 当我将代码更改为private java.util.Date modifiedTimestamp
时,自动映射似乎中断了,我收到此错误java.lang.NoSuchMethodError: com/myapp/domain/Widget.getModifiedTimestamp()Ljava/sql/Data
你必须重新编译 Widget.java ;有疑问时清理它。
【参考方案1】:
注释您的字段并更改类型应该会有所帮助:
@Temporal(TemporalType.TIMESTAMP)
private java.util.Date modifiedTimestamp;
【讨论】:
注意:为了使其正常工作,我还将 Oracle 字段更改为 TIMESTAMP 而不是 DATE。 在我的例子中(Oracle 11g),Oracle 中的 DATE 数据类型也可以工作。 不要这么认为 Calendar 已经很老了,我从未见过它与 JPA 一起使用。 “新”日期时间 API 在 java.time 中,但我从未将它与 JPA 一起使用,因为我近年来没有使用 java。实际上,我倾向于尽可能多地使用 JodaTime,因为它有一个更健全的 API,java.time 是基于它的。【参考方案2】:使用@Temporal(TemporalType.TIMESTAMP)
(Javadocs)。合并with java.util.Date。
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "DATE_FIELD")
private java.util.Date modifiedTimestamp;
【讨论】:
感谢@AnthonyAccioly,我想将其标记为正确,Eelke 在几秒钟内击败了您。 :) 感谢@AnthonyAccioly,我的案例中缺少 Column 注释,并根据您的建议进行了修复。【参考方案3】:我看到这个问题之前有人问过,所以我建议阅读 this 文章。引入 java 8 日期类型后有一些变化。我知道这不是这个问题的答案,而且我遇到的问题不同,但我发布这个是因为我在答案中看到的 @Temporal()
注释破坏了我的 CI 管道:
这行得通:
@NotNull
@Column(nullable = false, columnDefinition = "TIME") // this bit is different
@JsonFormat(pattern="HH:mm")
private LocalTime startTime;
这不是:
@NotNull
@Column(nullable = false)
@Temporal(TemporalType.TIME)
@JsonFormat(pattern="HH:mm")
private LocalTime startTime;
【讨论】:
【参考方案4】:如果您将类型更改为java.sql.Timestamp
,那么它也应该可以工作,而无需添加@Temporal
注释。
private java.sql.Timestamp modifiedTimestamp;
当然在 Oracle 中将字段更改为 TIMESTAMP。
【讨论】:
【参考方案5】:这就是我在 Java、mysql db 和 OpenJPA2 中处理日期时间字段的方式。我希望字段是 java.util.Calendar 类型,dbfield datetime 和 dbvalue 作为 UTC 值。 Mysql 对时区一无所知,因此使用自定义转换器可以设置和读取“yyyy-MM-dd HH:mm:ss”字符串。仍然是实体 bean 中的有效日期时间 sql 列和 java.util.Calendar。
@Entity @Table(name="user") @Access(AccessType.FIELD)
public class User
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private long id; // primary key (autogen surrogate)
private String name;
@Column(name="updated_utc") // use custom serializer so that UTC-stringified
@Temporal(TemporalType.TIMESTAMP) // db datetime is properly set to calendar instance
@Factory("JPAUtil.db2calendar") @Externalizer("JPAUtil.calendar2db")
private Calendar updated;
public long getId() return id;
public void setId(long id) this.id = id;
public String getName() return name;
public void setName(String name) this.name=name;
public Calendar getUpdated() return updated;
public void setUpdated(Calendar cal) updated=cal;
- - -
public class JPAUtil
public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
public static String calendar2db(Calendar val, StoreContext ctx)
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TIMEZONE_UTC);
return df.format(cal.getTime()); // return date as UTC string value
public static Calendar db2calendar(String val, StoreContext ctx)
try
// returned calendar is using a default timezone, val was set as utc string
return DateUtil.parseDateTimeFromUTC(val);
catch (Exception ex)
return null;
- - -
CREATE TABLE user (
id bigint NOT NULL auto_increment,
name varchar(64) NOT NULL default '',
updated_utc datetime NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY USERNAME (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
ps:DateUtil 是我的随机工具类,用于提供一些基本的转换。
【讨论】:
以上是关于如何在 Oracle 中使用 JPA 存储日期和时间?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JPA 将 Java 日期存储到 Mysql 日期时间
如何正确地转换成 java.util.Date 通过 JPA 的 Oracle 日期字段
使用 Spring Data Jpa 在 Oracle 中调用存储过程时参数的数量或类型错误