前段时间参照JFinal和etMVC自己写了一个简单ORM,起名就qm86-ar,qm86就是"秋名山的86"的意思,ar嘛就是ActiveRecord,以后也会逐步完善框架.来讲讲写ORM时遇到的一些问题吧.
首先来看看Oracle和MySQL中都有哪些常用的时间日期类型,我们说的时间嘛,就是HH:mm:ss的样子,由小时:分钟:秒组成的,而日期就是yyyy/MM/dd,由年/月/日组成
参考:http://www.alixixi.com/WebData/subject22/2005121362212596.html 和http://blog.163.com/yaoyingwei@126/blog/static/21498384200801991544439/
java的日期时间类型
说一下java的日期时间类型吧,
java.sql.Date 这个是为数据库提供日期类型,只包含年/月/日,注意不要跟java.util.Date弄混了,区别马上会讲到
java.sql.Time 为数据库提供的时间类型,只包含小时:分钟:秒,不包括毫秒
java.sql.Timestamp 为数据库提供的日期时间类型,同时包含日期和时间和毫秒部份
java.util.Date 是java的规范的时间类型,以上三个包都由它继承而来,它包含时间和日期不包含毫秒部分
所以我们很容易看出来了sql.Date和util.Date的区别在于,sql.Date只有年月日,util.Date有年月日和小时分钟秒,原来我还以为这两个是一样的,只是sql.Date是用在数据库中,后来出现了好多的错误….
注意,虽然说sql.Timestamp是由util.Date继承而来,但是sql.Timestamp比util.Date多包含了毫秒部分,JDK上写了Note: This type is a composite of a java.util.Date and a separate nanoseconds value. Only integral seconds are stored in the java.util.Date component. The fractional seconds – the nanos – are separate. 说明sql.Timestamp是由util.Date和小数部分组成的
Oracle
Oracle常用到的是DATE类型和TIMESTAMP类型
DATE:包含日期和时间,时间不包含小数,也就是说不会出现10.2秒这种情况
取值范围从公元前4712年1月1日至公元9999年12月31日
TIMESTAMP:也包含日期和时间,时间可以包含9位小数
在不包含小数位或小数位为0时,TIMESTAMP和DATE存储空间完整相同
诺小数位不为0时,oracle把小数部份当作一个9位数字来存,就像10.123456000秒
在JDBC中,通过ResultSet的getObject方法得到的数据类型
DATE为 java.sql.Timestamp
TIMESTAMP为 oracle.sql.TIMESTAMP
由于写的是ORM嘛,为个处理方便,Model中的时间日期类型我就全都设成是util.Date类型的,但是经验证,jdbc中oracle和mysql是不会返回util.Date类型的数据,所以通常会写一个转换功能类ConvertUtil来转换数据库返回数据的类型,先把getObject得到的数据value = ((java.sql.Timestamp)obj).toString(),再用new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)就可以转换成util.Date类型了
在向数据库中插入时间日期类型的数据时也要注意,如果要插入的是util.Date类型,必须先转型再插值
if(null != o&&o.getClass().getCanonicalName().equals("java.util.Date")){
pstmt.setTimestamp(i+1, new Timestamp((((java.util.Date)o)).getTime()));
}else{
pstmt.setObject(i + 1, o);
}
当然这些都是在你不需要毫秒的情况下,如果需要保留小数点.那就必须用sql.Timestamp类型啰
MySQL
MySQL常用到的是Date,Time,DateTime和TimeStamp类型
Date:只包含日期
支持的范围为'1000-01-01'到'9999-12-31'
Time:只包含时间
范围是'-838:59:59'到'838:59:59'
DateTime:包含日期和时间,不储存小数
支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'
Timestamp:包含日期和时间,不储存小数
范围是'1970-01-01 00:00:00'到2037年
从MySQL的使用手册中我们知道
A DATETIME or TIMESTAMP value can include a trailing fractional seconds part in up to microseconds (6 digits) precision. Although this fractional part is recognized, it is discarded from values stored into DATETIME orTIMESTAMP columns.
A trailing fractional seconds part is permissible for temporal values in contexts such as literal values, and in the arguments to or return values from some temporal functions.
However, when MySQL stores a value into a column of any temporal data type, it discards any fractional part and does not store it.
MySQL并不为我们存储带在小数的时间,而只是当你插入有毫秒的时间时,它会帮你处理成秒的形式储存,也不会显示毫秒,那要想储存毫秒怎么办呢?简单,把小数部分分离出来单独成一列存放不就行了吗?
在JDBC中,通过ResultSet的getObject方法得到的数据类型
Date =>java.sql.Date
Time => java.sql.Time
Timestamp=> java.sql.Timestamp
DateTime => java.sql.Timestamp
注意:sql.Timestamp类型是带有小数点的,当小数不存在时系统会自动补上0,如2013-01-24 13:22:35.0,所以在使用时要小心,简单的处理办法是用new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)来格式化一下就好了,注意月份是大写的M,分钟是小写的m哦
细心的同学可能会发现DateTime和Timestamp好像是一样的,只是取值范围不一样而已,那为什么是Timestamp的取值范围是1970-01-01 00:00:00'到2037年的某一天呢?学过UNIX的同学应该会知道吧?嘿嘿,Timestamp叫做时间戳,在MS还没出世UNIX广泛应用的时代,UNIX系统用一个叫做UNIX时间戳的32位二进制数来记录时间,时间从1970年1月1日起开始计时,每过一秒时间戳加1,不记录闰秒,这样就可以把时间有效的表示出来了,可是呢,2的32次方虽然很大也是有限个数呀,它的终点就是在2037年的某一天了,到那天会发生什么呢?进入21世纪时的千年虫事件就是最好的例子啰,前两年Iphone的元旦闹钟失效的bug也许也是时间代码也写好的原因吧.那到了2037年是不是很多东西都会失效呀?不会啦,据说现在的UNIX时间戳已经改成64位啦,2^64=18446744073709551616,到时候也不知道地球还存不存在哦~~~