- 浏览: 135481 次
- 性别:
- 来自: 重庆
文章分类
- 全部博客 (87)
- WebService (4)
- Spring (4)
- Tomcat (4)
- Eclipse (4)
- GWT (14)
- Servlet (4)
- OpenLayers (1)
- Java (13)
- JavaScript (4)
- tools (3)
- FusionCharts (8)
- FCKeditor (2)
- POI (1)
- Log4j (1)
- Util (8)
- jQuery (4)
- Hibernate (6)
- QuartZ (1)
- 异常 (2)
- JDBC (4)
- Oracle (2)
- Axis (1)
- CXF (1)
- Guzz (1)
- Activemq (1)
- ArcGis (2)
- Gilead (1)
- XML (1)
- HTML (1)
- 微软雅黑 字体清晰 (1)
- Android (1)
- Netty简介、架构、机制、特性 (1)
- Atomikos (1)
最新评论
-
dingding317:
这个问题也困扰了我很久,终于解决了!在tomcat启动脚本中加 ...
Could not initialize class net.sf.jasperreports.engine.util.JRStyledTextParser -
dipoo:
不错!全部收起来了,谢谢
数据库驱动包 -
mfkxk298:
bean-woo 写道mfkxk298 写道按照你的方法试了, ...
Gwt FusionCharts简单demo -
bean-woo:
mfkxk298 写道按照你的方法试了,成功了,感谢 。现在就 ...
Gwt FusionCharts简单demo -
mfkxk298:
按照你的方法试了,成功了,感谢 。现在就不知道xml文件中的中 ...
Gwt FusionCharts简单demo
JDBC操作MySQL5日期类型字段的问题解决方法
由于日期数据的特殊性和多样性,以及不同的数据库、编程语言对日期的定义和处理方式差别,导致了日期处理的复杂性,和多样性。
流行的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'。要想确保不使用严格模式时日期有效,应检查应用程序。
当你只需要日期值而不需要时间部分时应使用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;
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,字符串型的日期格式是正确的
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,字符串型的日期格式是正确的
String sql = "update testdate set crdate = '2009-12-12 13:33:15' where code = 'z'";
----------查询-----------------------------------
//对于查询,静态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,字符串型的日期格式是正确的
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 = "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"));
}
三、对于date类型,因为不带时分秒,用的较少。
四、JDBC操作timestamp和datetime时候应该注意的问题
1、JDBC读取时候,应该选择getTimestamp()方法来读取,这样才能保持数据精度。
如果选择了getDate读取,则自动丢弃时分秒,造成精度下降。
2、JDBC读取的数据保存为java类型时候,应该定义为java.util.Date,这样可以保持原有的精度,如果设置成java.sql.Date,则造成时分秒丢失。
3、java.sql.Date是Java历史的垃圾,尽量避免使用。
4、在执行预定义SQL的时候,java.lang.String参数似乎是更好的方式。
本文也许是此同类问题的一个开始话题,仅仅演示了MySQL中的高精度日期类型操作一些正确方法,并非全部,但这些结论仅仅局限于MySQL5.
本文出自 “熔 岩” 博客,请务必保留此出处http://lavasoft.blog.51cto.com/62575/224370
发表评论
-
JDBC 工具类
2013-02-05 09:46 706JDBC 工具类 -
Oracle常见命令操作
2012-06-01 09:22 10611. 创建表空间、用户、给用户授权: creat ... -
全面分析Java的垃圾回收机制
2011-11-17 09:42 541Java的堆是一个运行 ... -
数据库驱动包
2011-11-10 14:38 982包括oracle,mysql,sqlite,sqlserver ... -
Java读取properties文件两种方式
2011-11-02 11:17 822方式一: package com.gps.server.ut ... -
人民币(Rmb)数字转换大写(大写)
2011-10-31 12:26 1280package com.test; public ... -
载取字符串中的汉字
2011-10-29 20:17 681package com.appdev.test.s ... -
UUID 产生码
2011-10-29 20:17 942package com.core.util; / ... -
字符串String操作类
2011-10-28 16:42 1205/* * Licensed to the Apach ... -
java 邮件发送
2011-10-22 09:43 978package com.appdev.bsf.common.s ... -
MD5加密
2011-10-24 09:54 946package com.appdev.bsf.server.c ... -
java 用反射简单应用,将Object简单转换成map
2011-10-24 09:54 8917package com.appdev.bsf.server.c ... -
mysql,Access,sqlite数据库连接
2011-10-24 09:55 1258Access数据库简单操作: ... -
jdk Tomcat环境变量
2011-10-22 09:44 723JAVA_HOME C:\Program Files\Java ...
相关推荐
5. **数据映射**:将Excel数据与MySQL表的字段进行匹配。如果数据类型不一致,可能需要进行类型转换。 6. **数据导入**:使用SQL语句(如`INSERT INTO`)将数据批量插入到MySQL表中。对于大量数据,可以考虑使用`...
- 错误处理:编程导入时要考虑异常处理,如文件不存在、网络问题、数据类型不匹配等。 - 批量操作:为提高效率,通常采用批量插入而不是一条条插入。 - 大数据处理:对于非常大的Excel文件,可能需要分批导入或者...
### MySQL数据库教程知识点详解 #### 一、数据库概述 **1.1 数据库定义与历史** - **定义**: 数据库(Database)是指按照特定数据结构来组织、存储和管理数据的集合体。它不仅是一个简单的数据存储空间,还包含了对...
【MySQL函数与操作】 - **聚合函数**:`COUNT(*)`计算所有行,`COUNT(列)`计算非NULL值的数量。 - **统计函数**:`SUM`求和,`AVG`计算平均值,`MAX`和`MIN`找出最大值和最小值。 - **GROUP BY与HAVING**:`GROUP ...
在实现这些功能的过程中,开发者可能使用了Servlet、JSTL、EL(Expression Language)等JSP相关技术,以及JDBC(Java Database Connectivity)来连接和操作MySQL数据库。同时,为了保证代码的组织性和可维护性,可能...
开发者可以利用JDBC驱动程序与MySQL进行通信,执行SQL语句来存取数据。 源码数据库部分,我们可预期包括以下几个关键组成部分: 1. **实体类(Entity)**:这些类对应于数据库中的表,如用户(User)、花卉(Flower)...
通过JDBC,Java代码可以发送SQL语句到MySQL服务器,执行查询、插入、更新或删除操作。 5. **CRUD操作**:创建(Create)、读取(Retrieve)、更新(Update)和删除/Delete,这是任何数据库驱动的应用程序的基本功能。在...
开发者通过Java的JDBC(Java Database Connectivity)接口连接到MySQL数据库,执行SQL语句来读取、插入、更新和删除数据。在设计数据库时,需遵循规范化原则,确保数据的一致性和减少冗余,提高数据的存储效率。 ...
1. **图像数据类型**:大多数现代关系型数据库管理系统(RDBMS),如MySQL、SQL Server和Oracle,提供了特殊的数据类型来存储二进制大对象(BLOB,Binary Large Object),这可以用来存放图像数据。BLOB可以进一步...
5.明确到每一行的错误信息.(装载时会生成一个.err文件,里面有装载出错的每一行错误原因(少字段还是格式不符合要求等等)。 6.可以作为库使用在jsp等后台直接调用,将整个jar作为库,使用 OraLoad类的int ProcLoad...
- **题目**:2010年10月1日在mysql中表示方法正确的是:()。 - **选项**:A、“2010/10/01” B、“2010\10\01” C、“2010-10-01” D、“2010%10%01” - **正确答案**:C - **知识点解析**:在MySQL中,日期通常使用...
5. **Java编程与列表控件**:在Java编程中,ListCtrl中的LVITEM结构的LPARAM字段可用于实现排序功能。SetItemData函数与LPARAM的关系需要明确,避免混淆。同时,模板函数的声明和实现是C++编程中的一个重要概念,...
【程序员实习日记】这篇文档记录了一位实习程序员在工作中的学习和体验,主要涉及了Java Web开发中的核心技术栈,包括Struts、...通过不断学习和解决问题,实习程序员逐渐掌握了相关技能,也积累了宝贵的开发经验。
1. **图片数据类型**:大多数关系型数据库系统,如MySQL、PostgreSQL和Oracle,都提供了BLOB或与其类似的二进制数据类型来存储图片。BLOB可以分为不同的子类型,如TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB,分别对应...
- 如果使用Tomcat最新版本6存在兼容性问题,可以降级到版本5以解决问题。 - 安装微软的JDBC驱动程序,确保能够加载SQLServer2000的驱动库。 实习日记不仅记录了作者的技术学习,还展现了实习生活的情感色彩,从中...
3. **字段操作**:理解如何创建、修改和删除dbf文件中的字段。这包括定义字段的数据类型(如字符、数字、日期等)、长度和小数位数。 4. **记录操作**:添加新记录、读取单个或多个记录、更新现有记录以及删除记录...
在Java应用中,通常通过JDBC(Java Database Connectivity)API来与MySQL数据库进行交互。JDBC提供了一套标准接口,使得Java程序能够连接到各种数据库,执行SQL语句并处理结果。 在这个实例中,开发人员可能会涉及...
通过JDBC,开发者可以实现对各种类型数据库的操作,包括SQL Server、MySQL、Oracle等。本项目中,我们使用Java的JDBC接口连接和操作数据库,实现成绩管理的各项功能。 2.2 模块简介 系统分为两个主要模块:管理员...
【描述】提到"里面附加数据库还有源码",这意味着这个项目不仅包含JSP文件,还整合了一个数据库,可能是MySQL、SQLite或其他类型,用于存储和检索数据。源码的提供让学习者可以查看和理解项目的完整实现过程,有助于...
2. **CreditCard类**:表示信用卡,包括卡号、信用额度、已用额度、还款日等属性,以及相关操作方法。 3. **Transaction类**:记录用户的消费和还款记录,包括交易金额、日期、类型等信息。 4. **UserController类**...