JDBC操作MySQL5日期类型字段的问题解决方法

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介:
由于日期数据的特殊性和多样性,以及不同的数据库、编程语言对日期的定义和处理方式差别,导致了日期处理的复杂性,和多样性。
 
流行的Hibernate、iBatis等持久化框架从中解决了各种Java日期与数据库日期之间操作的细节问题,JDBC操作数据库日期的问题已经被淡化了。但是对于纯JDBC开发者来说,这些问题不可小觑。
 
下面以MySQL5和Java5为基础,说明Java处理数据库日期的一些问题及解决方案。
 
认识MySQL的日期类型:
列类型
”值
DATETIME
'0000-00-00 00:00:00'
DATE
'0000-00-00'
TIMESTAMP
00000000000000
TIME
'00:00:00'
YEAR
0000
从零值类型,也可以清晰看出日期的格式,再次,并不想讨论所有的数据类型,二是针对前三种常用类型做以分析。
 
MySQL日期类型的一些说明:
当你需要同时包含日期和时间信息的值时则使用DATETIME类型。MySQL以'YYYY-MM-DD HH:MM:SS'格式检索和显示DATETIME值。 
当你只需要日期值而不需要时间部分时应使用DATE类型。MySQL用'YYYY-MM-DD'格式检索和显示DATE值。 
TIMESTAMP列类型的属性不固定,取决于MySQL版本和服务器运行的SQL模式。 
TIMESTAMP列的显示格式与DATETIME列相同。换句话说,显示宽度固定在19字符,并且格式为YYYY-MM-DD HH:MM:SS。 

在一定程度上,可以将一个日期类型的值分配给一个不同的日期类型。但是,值可能会更改或丢失一些信息: 

·                 如果你为一个DATETIME或TIMESTAMP对象分配一个DATE值,结果值的时间部分被设置为'00:00:00',因为DATE值未包含时间信息。 

·                 如果你为一个DATE对象分配一个DATETIME或TIMESTAMP值,结果值的时间部分被删除,因为DATE值未包含时间信息。 

·                 记住尽管可以使用相同的格式指定DATETIME、DATE和TIMESTAMP值,不同类型的值的范围却不同。例如,TIMESTAMP值不能早于1970或晚于2037。这说明一个日期,例如'1968-01-01',虽然对于DATETIME或DATE值是有效的,但对于TIMESTAMP值却无效,如果分配给这样一个对象将被转换为0。 

当指定日期值时请注意某些缺陷: 

·                 指定为字符串的值允许的非严格格式可能会欺骗。例如,值'10:11:12'由于‘:’间割符看上去可能象时间值,但如果用于日期上下文值则被解释为年'2010-11-12'。值'10:45:15'被转换为'0000-00-00'因为'45'不是合法月。 

·                 在非严格模式,MySQL服务器只对日期的合法性进行基本检查:年、月和日的范围分别是1000到9999、00到12和00到31。任何包含超出这些范围的部分的日期被转换成'0000-00-00'。请注意仍然允许你保存非法日期,例如'2002-04-31'。要想确保不使用严格模式时日期有效,应检查应用程序。
 
 
问题:
对于JDBC写入MySQL数据库类型发生时分秒丢失的问题。
从数据库读出日期,时分秒丢失问题。
增删改查日期类型字段发生传参等错误的问题。
 
对于以上的问题,是非常普遍的。这里从数据库日期类型的精度需求入手,以MySQL5为蓝本,以JDBC为访问手段,研究日期的操作。
 
环境:
Java5
mysql-noinstall-5.1.40-win32.zip
mysql-connector-java-5.1.10.zip
 
一、要求最高精度的日期数据,timestamp类型,这种日期类型带最高精度,但与数据库设置有关系,一般默认即可。
 
 
建表SQL
create  database    

use testdb; 

drop  table  if  exists testdate; 

create  table testdate ( 
    id  bigint(20)  not  null auto_increment, 
    code  varchar(20)  default  null
    crdate  timestamp  not  null  default  current_timestamp
     primary  key (id) 
) engine=myisam auto_increment=122  default charset=latin1;
 
测试结论:
  ----------插入----------------------------------- 
   //对于插入,静态SQL,字符串型的日期格式是正确的 
  String sql_1 =  "insert into testdate(code,crdate) values ('x',CURRENT_TIMESTAMP)";    
  String sql_2 =  "insert into testdate(code,crdate) values ('y','2009-11-09 13:00:23')";    

   //对于插入,预定义SQL,java.sql.Timestamp型的日期格式参数是正确的 
  String sql =  "insert into testdate(code,crdate) values ('z',?)";    
  PreparedStatement pstmt = conn.prepareStatement(sql);    
  pstmt.setTimestamp(1,  new Timestamp(System.currentTimeMillis()));    

   //对于插入,预定义SQL,java.lang.String型的日期格式参数是正确的 
  String sql =  "insert into testdate(code,crdate) values ('w',?)";    
  PreparedStatement pstmt = conn.prepareStatement(sql);    
  pstmt.setString(1,  "2009-11-09 13:00:23");    

  ----------更新----------------------------------- 
   //对于更新,静态SQL,字符串型的日期格式是正确的 
  String sql =  "update testdate set crdate = '2009-12-12 13:33:15' where code = 'z'";    

   //对于更新,预定义SQL,java.lang.String型的日期格式参数是正确的 
  String sql =  "update testdate set crdate = ? where code = 'z'";    
  PreparedStatement pstmt = conn.prepareStatement(sql);    
  pstmt.setString(1,  "2009-12-12 13:33:15");    

  ----------查询----------------------------------- 

   //对于查询,静态SQL(两种写法),java.lang.String型的日期格式参数是正确的 
  String sql =  "select * from testdate where crdate > '2009-11-09 13:00:23' and crdate < '2009-11-10 13:00:23'";    
  String sql =  "select * from testdate where date_format(crdate, '%Y-%c-%e %T') between '1900-2-1 00:00:00' and '2010-2-5 00:00:00'"
  Statement stmt = conn.createStatement();    
  ResultSet rs = stmt.executeQuery(sql);    
   while (rs.next()) {    
    System.out.println( ">>> id=" + rs.getLong( "id") +  "; code=" + rs.getString( "code") +  "; crdate=" + rs.getTimestamp( "crdate"));    
  }    


   //但对于查询,预定义SQL,java的字符串和Timestamp类型参数都是错误的,不能执行,会提示语法错误。 
   //但别的数据库就另当别论了。 
  pstmt.setString(1, "2009-11-09 13:00:23"); 
  pstmt.setString(2, "2009-11-10 13:00:23"); 
  pstmt.setTimestamp(1, new Timestamp(sf.parse( "2009-11-09 13:00:23").getTime())); 
  pstmt.setTimestamp(2, new Timestamp(sf.parse( "2009-11-10 13:00:23").getTime()));
 
可以看出,字符串类型还是支持比较好。在SQL和Java语言之间都能良好的支持。
 
二、要求高精度的日期数据,选择datetime类型,这种日期格式带时分秒,用的较多。
 
对于上面表的crdate类型改下即可。
测试结论是:
  ----------插入----------------------------------- 
   //对于插入,静态SQL,字符串型的日期格式是正确的 
  String sql_1 =  "insert into testdate(code,crdate) values ('x',CURRENT_TIMESTAMP)";    
  String sql_2 =  "insert into testdate(code,crdate) values ('y','2009-11-09 13:00:23')";    

   //对于插入,预定义SQL,java.sql.Timestamp型的日期格式参数是正确的 
  String sql =  "insert into testdate(code,crdate) values ('z',?)";    
  PreparedStatement pstmt = conn.prepareStatement(sql);    
  pstmt.setTimestamp(1,  new Timestamp(System.currentTimeMillis()));    

   //对于插入,预定义SQL,java.lang.String型的日期格式参数是正确的 
  String sql =  "insert into testdate(code,crdate) values ('w',?)";    
  PreparedStatement pstmt = conn.prepareStatement(sql);    
  pstmt.setString(1,  "2009-11-09 13:00:23");    

  ----------更新----------------------------------- 
   //对于更新,静态SQL,字符串型的日
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11天前
|
Java 数据库连接
【YashanDB知识库】JDBC驱动的date类型字段结果集调用getString方法只返回日期,不返回时分秒
【YashanDB知识库】JDBC驱动的date类型字段结果集调用getString方法只返回日期,不返回时分秒
|
13天前
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为&#39;0&#39;或&#39;1&#39;,查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
7天前
|
关系型数据库 MySQL Java
【YashanDB知识库】崖山BIT类型对MYSQL兼容问题
【YashanDB知识库】崖山BIT类型对MYSQL兼容问题
|
10天前
|
自然语言处理 关系型数据库 MySQL
MySQL索引有哪些类型?
● 普通索引:最基本的索引,没有任何限制。 ● 唯一索引:索引列的值必须唯一,但可以有空值。可以创建组合索引,则列值的组合必须唯一。 ● 主键索引:是特殊的唯一索引,不可以有空值,且表中只存在一个该值。 ● 组合索引:多列值组成一个索引,用于组合搜索,效率高于索引合并。 ● 全文索引:对文本的内容进行分词,进行搜索。
|
2天前
|
SQL 关系型数据库 MySQL
【YashanDB 知识库】YashanDB 支持 MySQL 多表更新语句的解决方法
【YashanDB 知识库】YashanDB 支持 MySQL 多表更新语句的解决方法
|
5天前
|
SQL 关系型数据库 MySQL
【YashanDB知识库】YashanDB 支持MySQL多表更新语句的解决方法
本文介绍了在YashanDB中处理MySQL多表更新语句的方法。由于YashanDB默认不支持多表更新(报错YAS-04344),可通过启用兼容性参数`SQL_PLUGIN = &#39;MYSQL&#39;`解决,或改写SQL语句实现相同功能。文章通过具体示例说明了多种改写方法,包括根据共同列更新单个或多个字段、添加过滤条件以及基于多个共同列的更新场景。涉及的表结构和数据展示了实际操作过程,帮助用户顺利迁移和使用YashanDB。
|
1月前
|
Java 数据库连接
【YashanDB 知识库】JDBC 驱动的 date 类型字段结果集调用 getString 方法只返回日期,不返回时分秒
**问题简介:** 在使用 JDBC 驱动查询 YashanDB 的 date 类型字段时,直接调用 ResultSet 的 getString 方法仅返回 YYYY-MM-DD 格式的日期字符串,缺少时分秒信息,影响业务逻辑。此问题存在于所有 YashanDB 驱动版本,原因是驱动内部实现问题。解决方法包括使用 `rs.getTimestamp(1).toString()` 或在 JDBC 连接串中添加 `mapDateToTimestamp=true` 参数。 **风险及影响:** 返回的字符串只有日期部分,缺失时间信息,可能导致业务逻辑异常。
|
1月前
|
Java 数据库连接
【YashanDB 知识库】JDBC 驱动的 date 类型字段结果集调用 getString 方法只返回日期,不返回时分秒
**问题简介:** 在使用 JDBC 驱动查询 YashanDB 中的 date 类型字段时,直接调用 ResultSet 的 getString 方法仅返回日期部分(YYYY-MM-DD),缺少时分秒信息,影响业务逻辑。此问题存在于所有 YashanDB 驱动版本,原因是驱动内部实现问题。解决方法:使用 `rs.getTimestamp(1).toString()` 或在连接串中增加 `mapDateToTimestamp=true` 参数。 **风险及影响:** 返回字符串缺少时分秒,可能导致业务逻辑错误。 **受影响版本:** 所有 YashanDB 驱动版本。
|
2月前
|
机器学习/深度学习 关系型数据库 MySQL
mysql bit对gorm使用何种类型?
在GORM中使用MySQL的BIT类型时,通常使用 `bool`类型来处理BIT(1),使用 `[]byte`类型来处理BIT(N)(N > 1)。通过正确的类型映射和位操作,可以高效地处理位字段数据。确保在定义结构体字段时,明确指定字段类型,以便GORM能够正确地处理数据库交互。
69 18
|
1月前
|
存储 SQL 关系型数据库
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据

推荐镜像

更多