我想将LocalDate
存储在DATE
列中并以未更改方式检索它。根据定义,DATE
和LocalDate
都是“本地”类型。因此,时区的概念不应以任何方式干涉。如何将sql日期映射到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
方法,使其返回相同的值那是无条件插入,假设数据库表没有改变?
你导入java.util.Date?在'retrieve ='行上,您可以在赋值左侧使用完全限定的'java.sql.Date',但不是正确的。 –
你为什么期待3个相同的'LocalDate'被打印?你插入日期'2015-05-20'。然后,当您更改默认时区时,java.sql.Date.toLocalDate方法将返回不同的结果。 – Tunaki
@BasilBourque固定 –