【发布时间】:2016-10-13 06:17:20
【问题描述】:
我想将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,每次使用不同的时区设置:
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));
}
}
然后打印以下内容:
插入: 2015-05-20 检索时间:2015-05-20 检索时间:2015-05-19 检索时间:2015-05-18假设数据库表没有改变,如何编写retrieve方法,使其返回插入无条件的相同值?
【问题讨论】:
-
你在导入 java.util.Date 吗?在
retrieved =行中,您在分配的左侧使用完全限定的java.sql.Date而不是右侧。 -
您为什么希望打印 3 个相同的
LocalDate?您正在插入日期2015-05-20。然后,当您更改默认时区时,java.sql.Date.toLocalDate方法将返回不同的结果。 -
@BasilBourque 已修复
-
为了不被隐含地绑定到系统时区,我希望(或希望)在这里出错,但我只会使用
String和return LocalDate.parse(rs.getString("born"));... -
@LarsBohl 我认为它只有效,因为 H2 存储 DATE as yyyy-MM-dd,而不是我推荐的东西。但是,我发现这篇文章stackoverflow.com/questions/32548331/… 并且问题中的代码似乎可以解决这个问题(即,如果您使用提供的
getLocalDate)。
标签: java jdbc timezone java-8 sqldatetime