![](/img/trans.png)
[英]How to map LocalDate to Date using Dozer or ModelMapper?
[英]How to map sql DATE to LocalDate
我想將LocalDate
存儲在DATE
列中並保持不變。 根據定義, DATE
和LocalDate
均為“本地”類型。 因此, 時區的概念不應以任何方式干涉。
下面的代碼是一個最小示例,該示例在內存數據庫中創建一個帶有DATE
列的表。 Maven工件com.h2database:h2:1.4.192
必須在類路徑中。
首先,定義insert
和retrieve
方法:
static void insert(DataSource ds, String date) throws SQLException {
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE people (id BIGINT NOT NULL AUTO_INCREMENT"
+ ", born DATE NOT NULL, PRIMARY KEY (id) );");
stmt.execute("INSERT INTO people (born) VALUES ('" + date + "')");
}
}
static LocalDate retrieve(DataSource ds) throws SQLException {
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM people limit 1")) {
if (rs.next()) {
java.sql.Date retrieved = java.sql.Date.valueOf(rs.getString("born"));
return retrieved.toLocalDate();
}
throw new IllegalStateException("No data");
}
}
注意, insert
方法在單引號中使用LocalDate
的toString
值,因此Java™沒有機會創建時區歧義。 現在打電話insert
一次,然后多次retrieve
,每次用不同的timzone設置:
public static void main(String[] args) throws Exception {
DataSource ds = JdbcConnectionPool.create("jdbc:h2:mem:test", "sa", "sa");
LocalDate born = LocalDate.parse("2015-05-20");
insert(ds, born.toString());
System.out.println("Inserted: " + born);
for (int i : new int[]{-14, 0, 12}) {
TimeZone z = TimeZone.getTimeZone(String.format("Etc/GMT%+02d", i));
TimeZone.setDefault(z);
System.out.println("Retrieved: " + retrieve(ds));
}
}
然后打印以下內容:
Inserted: 2015-05-20 Retrieved: 2015-05-20 Retrieved: 2015-05-19 Retrieved: 2015-05-18
假設數據庫表不變,如何編寫retrieve
方法,使其返回無條件插入的相同值?
我只是嘗試對您的retrieve
方法進行以下修改,但對我有用:
日期數據類型。 格式為yyyy-MM-dd。
所以,而不是你的...
java.sql.Date retrieved = (java.sql.Date) rs.getObject("born");
return retrieved.toLocalDate();
我剛用過
return LocalDate.parse(rs.getString("born"));
...和我的代碼產生
Inserted: 2015-05-20
Retrieved: 2015-05-20
Retrieved: 2015-05-20
Retrieved: 2015-05-20
以下解決方案也適用。 我更喜歡在接受的答案中通過String
進行轉換,因為它避免了如下所示的時區調整。 但是,它可能無法在所有數據庫上以相同的方式工作,因為某些數據庫(例如Oracle)具有不同的DATE
定義。
static LocalDate retrieve(DataSource ds) throws SQLException {
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM people limit 1")) {
if (rs.next()) {
ZoneId utc = ZoneId.of("UTC");
TimeZone z = TimeZone.getTimeZone(utc);
Calendar cal = Calendar.getInstance(z);
java.sql.Date retrieved = rs.getDate("born", cal);
long time = retrieved.getTime();
java.util.Date utilDate = new java.util.Date(time);
Instant instant = utilDate.toInstant();
ZonedDateTime zdt = instant.atZone(utc);
return zdt.toLocalDate();
}
}
throw new IllegalStateException("No data");
}
正如用戶Tunaki所建議的那樣,此問題概述了通過java.util.Date
的轉換:是否缺少在Java 8中修復JDBC日期處理的機會?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.