背景
前些天要做一个公开课管理模块,里边刚好有张表里边的字段有日期类型,纠结着是存成date还是varchar2,后来又想到可能还会有两个日期之间的天数,所以存成了date类型。本想着往Oracle中存个date很简单吧,没成想全是坑啊,现在分享下我踩的坑!!!
在数据库中研究下Date类型
INSERT INTO publiclesson VALUES('01',date'2019-07-04','暑期安全讲座','吴永勤','学生会','扇形报告厅','全体暑期留校人员都要参加','点到');
请注意我的date类型写法: date’2019-07-04’
然而存完后 存成了这样04-7月 -19
这是因为Oracle 默认的显示格式是 DD-MON-YY
这就不太好了,存成这样不好看啊
幸好Oracle中提供强大的转化函数 TO_CHAR(date, ‘YYYY-MM-DD’) 可以将date类型转化为自己想要的类型
SELECT TO_CHAR(startdate, 'YYYY-MM-DD') AS startdate FROM publiclesson;--2019-07-04
这样是不是太累了,每次都要转化一下,就没有简单的方法吗?
设置Oracle默认格式
ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD';--设置Oracle的默认date格式
设置完默认格式,就可以将date直接存,直接取了;感觉整个世界都清静了有木有
INSERT INTO publiclesson VALUES('01','2019-07-04','暑期安全讲座','吴永勤','学生会','扇形报告厅','全体暑期留校人员都要参加','点到');
SELECT startdate FROM publiclesson;
用Java语言往Oracle存date
先试探性的看了下PreparedStatement中有没有setdate()这种方法,当我看到
void setDate(int parameterIndex, java.sql.Date x) throws SQLException;
我放心了,应该能玩起来
添加代码(包含日期类型)
public int addPublicLesson(PublicLesson lesson) {
Connection conn = DBUtilDruid.getConnection();
PreparedStatement pstm = null;
int count = 0;
String sql = "INSERT INTO publiclesson VALUES(?,?,?,?,?,?,?,?)";
try {
pstm = conn.prepareStatement(sql);
pstm.setString(1, lesson.getId());
pstm.setDate(2, lesson.getStartdate());
pstm.setString(3, lesson.getTech_title());
pstm.setString(3, lesson.getTech_title());
pstm.setString(4, lesson.getSpeaker());
pstm.setString(5, lesson.getOrganizer());
pstm.setString(6, lesson.getAddress());
pstm.setString(7, lesson.getGroup_note());
pstm.setString(8, lesson.getRemark());
count = pstm.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtilDruid.close(conn, pstm);
}
return count;
}
测试一下
这里不得不说下,因为不知道怎么声明date类型特意查了API文档,看了下有关时间的有三个分别是Date Time Timestamp,结果发现他们三兄弟的构造方法都被弃用了,好坑啊,都到这儿了。本着不能放弃的精神,写了以下测试代码
@Test
public void testAddPulicLesson() {
Date date = new Date(2019,7,5);
PublicLesson lesson = new PublicLesson("01",date,"暑期安全讲座","吴永勤","学生会","扇形报告厅","全体暑期留校人员都要参加","点到");
logger.info(ipld.addPublicLesson(lesson));
}
测试成功(添加了一条记录)
然而打开数据库想验证下,瞬间傻眼了,这是什么?3919-07-05
静下来一分析,只有年不对呀,我也没写差呀
突然脑子一闪,应该 原始时间不是从0开始的 一看API果不其然,人家 从1970年1月1日开始的
难道我每次都要减个差值吗?那也太累了?
又看了下API,看到了 static Date valueOf(String s)将JDBC日期转义格式的字符串转换为 Date值,这应该就是没差值的方法了吧
再试一把
结果OK,没问题,看来人家弃用构造方法没毛病啊
看看别人的做法
感觉我的做法很复杂,Oracle中存date,Java中放date,而这两个date匹配度太差,导致有很多不必要的操作
网上搜索了一下,果然有大佬
利用Oracle中内置方法 **to_date(String s, 'yyyy-mm-dd ')**可以不用将java中存储出date类型,用String操作,简化了对date类型的操作
// 修改程序
String sql = "INSERT INTO publiclesson VALUES(?,to_date(?, 'yyyy-mm-dd'),?,?,?,?,?,?)";
pstm.setString(2, lesson.getStartdate());//注意我这里是String类型的
// 测试时直接传String字符串就行
PublicLesson lesson = new PublicLesson("01","2019-07-05","暑期安全讲座","吴永勤","学生会","扇形报告厅","全体暑期留校人员都要参加","点到");
// 检索SQL也是如此
String sql = "SELECT speaker,organizer FROM publiclesson WHERE startdate = to_date(?, 'yyyy-mm-dd')";
一点小问题还是补充下吧,SELECT to_char(startdate,'yyyy-mm-dd') a,speaker,organizer FROM publiclesson
这种语句检索出来的数据带有时分秒,但我的数据库中没有放,所以不想让他显示
下面给出解决方案
String sql = "SELECT to_char(startdate,'yyyy-mm-dd') startdate,speaker,organizer FROM publiclesson;// 注意我的别名,不写汇报错的
上边的to_char(x,x)很好理解,从数据库中读数据以一定格式显示,关键是这个操作把列名改了,所以我们要把列名给更正回去
好了,就到这里了,总结一下
总结
往Oracle中存date目前已有两种方法了:
- 踩坑踩出来的方法一,数据库存date,Java中存date(java.sql.date),其中使用到了valueOf(),缺点很明显,操作复杂
- 网上搜索到的方法二(我很看好),数据库存date,Java中存String, 其中用到了Oracle的内置函数to_char和to_date,在Java中操作变简单了,都是操作String或int
做完了,坑也踩得差不多了,相信下次开发时遇到绝对溜溜的