2013-10-16 27 views
-2

我发现没有办法将日期/时间插入到标准区域(如UTC中)的MySQL数据库中。将特定区域的日期/时间插入到MySQL数据库中

以下代码段使用Apache DBCP对用户进行身份验证。

public final class AuthenticationDAO { 

    public boolean isAuthenticated(String userName, String password) throws SQLException { 
     Connection connection = null; 
     PreparedStatement preparedStatement = null; 
     ResultSet resultSet = null; 
     boolean status = false; 

     try { 
      connection = DatabaseConnection.getConnection(); 
      preparedStatement = connection.prepareStatement("select * from admin_tbl where lower(admin_id)=lower(?) and BINARY password=?"); 
      preparedStatement.setString(1, userName); 
      preparedStatement.setString(2, password); 
      resultSet = preparedStatement.executeQuery(); 
      status = resultSet.next(); 

      if (status) { 
       preparedStatement = connection.prepareStatement("update admin_tbl set last_login=? where lower(admin_id)=lower(?) and BINARY password=?"); 
       preparedStatement.setTimestamp(1, new Timestamp(new Date().getTime())); // java.util.Date/java.sql.Timestamp 
       preparedStatement.setString(2, userName); 
       preparedStatement.setString(3, password); 
       preparedStatement.executeUpdate(); 
      } 
     } finally { 
      if (connection != null) {connection.close();} 
      if (resultSet != null) {resultSet.close();} 
      if (preparedStatement != null) {preparedStatement.close();} 
     } 
     return status; 
    } 
} 

此代码只有一行符合我们的兴趣。

preparedStatement.setTimestamp(1, new Timestamp(new Date().getTime())); 

当用户/管理员的登录尝试成功时,此行更新登录日期/时间。 MySQL中的列last_login的类型为DATETIME


我想插入日期/时间在MySQL中没有发生的UTC区。它似乎需要一个本地区域。

通过任何方式,是否可以在UTC区插入日期/时间到MySQL中? Java和/或MySQL中的任何数据类型都可能被建议 - 不仅仅是我在这里介绍的。

回答

0

Date是Java中时区不可知的。它始终以UTC(默认和始终)。因此,DateTimestamp本身不是原因,但是当Date/Timestamp通过JDBC驱动程序传递到数据库时,它将依据JVM时区依次解释日期/时间(默认为系统时区)(本机操作系统区)。

因此,除非明确强制MySQL JDBC驱动程序使用UTC区域或JVM本身设置为使用该区域,否则即使配置了MySQL本身,它也不会使用UTC将Date/Timestamp存储到目标数据库中使用default_time_zone='+00:00'my.inimy.cnf[mysqld]部分中使用UTC。有些数据库如Oracle可能支持带时区的时间戳,也可能是我不熟悉的一个例外(未经测试,因为我目前没有该环境)。

void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException

使用给定日历对象中的指定参数设置为给定值java.sql.Timestamp, 。驱动程序使用日历对象 构造一个SQL TIMESTAMP值,然后驱动程序将该值发送到 数据库。使用Calendar对象时,驱动程序可以计算考虑到自定义时区的 时间戳。 如果没有指定Calendar对象 ,则驱动程序使用默认时区,即运行应用程序的虚拟机的默认时区为 。

同样的事情还提到了其他相关的getter和setter方法处理日期,时间在java.sql.PreparedStatement类。

这可以通过检查MySQL JDBC驱动程序实现的setTimestampInternal()方法的调用来进一步阐明。

请参阅以下two调用方法的两个重载版本中的setTimestampInternal()方法。

/** 
* Set a parameter to a java.sql.Timestamp value. The driver converts this 
* to a SQL TIMESTAMP value when it sends it to the database. 
* 
* @param parameterIndex the first parameter is 1... 
* @param x the parameter value 
* 
* @throws SQLException if a database access error occurs 
*/ 
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { 
    setTimestampInternal(parameterIndex, x, this.connection.getDefaultTimeZone()); 
} 

/** 
* Set a parameter to a java.sql.Timestamp value. The driver converts this 
* to a SQL TIMESTAMP value when it sends it to the database. 
* 
* @param parameterIndex the first parameter is 1, the second is 2, ... 
* @param x the parameter value 
* @param cal the calendar specifying the timezone to use 
* 
* @throws SQLException if a database-access error occurs. 
*/ 
public void setTimestamp(int parameterIndex, java.sql.Timestamp x,Calendar cal) throws SQLException { 
    setTimestampInternal(parameterIndex, x, cal.getTimeZone()); 
} 

因此,当与PreparedStatement#setTimestamp()方法没有指定Calendar例如,默认时区将被使用(this.connection.getDefaultTimeZone())或与所提供的Calendar实例中指定时区将被使用(cal.getTimeZone()) 。

因此,只需将java.util.Calendar或其子类java.util.GregorianCalendar的实例传递给您感兴趣的合适时区(我们感兴趣的UTC)的PreparedStatement#setTimestamp()

Timestamp timestamp = new Timestamp(new java.util.Date().getTime()); 
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 

preparedStatement.setTimestamp(1, timestamp, calendar); 

指定的时区将被用于生成Timestamp的字符串表示它传递到底层数据库之前被提供。


如果你碰巧对付像Hibernate,EclipseLink的一个ORM框架,使用适当的数据源中的应用服务器/ Servlet容器创建一个连接池沿,然后参考this answer这个答案是基于并且是直接复制而来。

1

您可以在两个地方为您的mySQL数据设置时区:全局配置和会话配置。你不能指定为mysql'这个日期是GMT,但这个日期是EST'。你必须将它们转换为共同的时区。

最佳做法是将您的服务器设置为特定的时区[例如:GMT],并​​确保您在存储过程中相应地转换日期/时间。实际上,所有后端数据都应该使用单个时区,并且任何转换都应该在输出之前立即进行。

相关问题