`
leonzhx
  • 浏览: 797117 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java TimeZone ++: mapping Calendar to Oracle Date or TimeStamp

 
阅读更多

zz Java TimeZone ++: mapping Calendar to Oracle Date or TimeStamp

 

 

 

(original article : http://blog.sarathonline.com/2009/01/java-timezone-mapping-calendar-to.html )

In Oracle Database date and timestamp columns can be read in java using s[g]etTimeStamp() methods for storing date and time information. However, they do not save the TimeZone information! The read and write operations are done on java.sql.TimeStamp which is a subclass of java.util.Date. When reading and writing to database, they just write out the *face value* in Java VM's default TimeZone the code is running on. And read the value too 'TO' the java VM's Default TimeZone. So assuming you WriteDate program on a VM in EST and ReadDate program on another VM in PST (or just change system timezone) - You are getting a different *value* in the date Object.

So, How do you tackle this issue. The best way is to set your application to run on a specified (constant) default timezone. As mentioned in the earlier post this can be achieved by TimeZone.setDefault(). If you are unable to do it, JDBC specification allows sql dates to be read and written using a specified calendar. The resultSet.s[g]etTimeStamp method has an overloaded cousin, that takes a Calendar parameter. These methods save the date *face value* into the db after converting it to the timezone of the calendar passed as argument. So if there is a central place, You would want to have code some thing like this.

staticfinalCalendar networkCal =Calendar.getInstance(TimeZone.getTimeZone("EST"));//Writing somewherePreparedStatement ps = conn.prepareStatement("Update datex set dt = ?, tms = ?, faceval =? where id=1");
 ps.setDate(1,new java.sql.Date(userDate.getTime()));
 ps.setTimestamp(2,newTimestamp(userDate.getTime()),networkCal);//Reading ElsewhereResultSet rs = st.executeQuery("select * from datex where id = 1");
 sqlTS = rs.getTimestamp("tms",networkCal);


In iBatis (we use iBatis), You can have a TypeHandlerCallback for Calender-TimeStamp mapping

classCalendarTypeHandlerCallbackimplementsTypeHandlerCallback{privatestaticfinalCalendar netWorkCal =Calendar.getInstance(TimeZone.getTimeZone("EST"));publicObject getResult(ResultGetter getter)throwsSQLException{Date date = getter.getDate(netWorkCal);Calendar calendar =null;if(date !=null){
            calendar =Calendar.getInstance();
            calendar.setTime(date);}return calendar;}publicvoid setParameter(ParameterSetter setter,Object parameter)throwsSQLException{GregorianCalendar calendar =(GregorianCalendar) parameter;
        java.sql.Date date =new java.sql.Date(calendar.getTimeInMillis());
        setter.setDate(date, netWorkCal);}publicObject valueOf(String s){return s;}}

A Sample jdbc test case is:

/**
 *  Table used:
  CREATE TABLE  "DATEX" 
   (	"ID" NUMBER(3,0) NOT NULL ENABLE, 
	"DT" DATE, 
	"TMS" DATE NOT NULL ENABLE, 
	"FACEVAL" VARCHAR2(50) NOT NULL ENABLE, 
	 CONSTRAINT "DATEX_PK" PRIMARY KEY ("ID") ENABLE
   )

 * 
 * @author spandurangi
 *
 */
public class DBTimeStampReadWriteTest extends TestCase {

	TimeZone userTz = TimeZone.getTimeZone("IST");

	//Used for writing TO and reading FROM RDBMS
	static final Calendar networkCal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
	String userEntered = "2009-01-31 01:00:01";

	/**
	 * @throws Exception
	 */
	public void testDirectWriteConvToSTDTz() throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		sdf.setTimeZone(userTz);
		Date userDate = sdf.parse(userEntered);

		System.out.println("========== DATABASE testDirectWriteConvToSTDTz TEST =================");
		Connection conn = null;
		try {
			conn = getConnection();
			PreparedStatement ps = conn.prepareStatement("Update datex set dt = ?, tms = ?, faceval =? where id=1");
			ps.setDate(1, new java.sql.Date(userDate.getTime()));
			ps.setTimestamp(2, new Timestamp(userDate.getTime()), networkCal);
			ps.setString(3, userEntered + " p/w " + sdf.getTimeZone().getID());
			ps.execute();

			Statement st = conn.createStatement();
			String SELECT_LATEST = "select * from datex where id = 1";
			Calendar ret = printRow(st.executeQuery(SELECT_LATEST));
			assertEquals(userDate,ret.getTime());

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.close();
			}
		}
	}


	/**
	 * Run this test seperately with Vm's TZ same after doing the first one
	 * @throws Exception
	 */
	public void testDirectReadConvToSTDTz() throws Exception {
		TimeZone.setDefault(TimeZone.getTimeZone("PST"));
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		// to compare the same value!!
		sdf.setTimeZone(userTz);
		Date userDate = sdf.parse(userEntered);

		System.out.println("========== DATABASE testDirectReadConvToSTDTz TEST =================");
		Connection conn = null;
		try {
			conn = getConnection();
			Statement st = conn.createStatement();
			String SELECT_LATEST = "select * from datex where id = 1";
			Calendar ret = printRow(st.executeQuery(SELECT_LATEST));
			assertEquals(userDate,ret.getTime());
			//Comparision may run on any vm!
			Calendar org = Calendar.getInstance();
			org.setTime(userDate);
			ret.setTimeZone(org.getTimeZone());
			System.out.println(decorate(org) + " == " + decorate(ret));
			assertEquals(decorate(org), decorate(ret));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.close();
			}
		}
	}



	private String decorate(Calendar cal) {

		FastDateFormat f = FastDateFormat.getInstance("EEE MMM dd HH:mm:ss z yyyy");
		return f.format(cal);
	}

	private Connection getConnection() throws Exception {
		Class.forName("oracle.jdbc.OracleDriver");
		String url = "jdbc:oracle:thin:@localhost:1521:xe";

		return DriverManager.getConnection(url, "sarath", "pass");
	}

	private Calendar printRow(ResultSet rs) throws Exception {
		rs.next();
		// JDBC driver reads by face value, loses date info
		java.sql.Date sqlDate = rs.getDate("dt");
		Calendar cal = Calendar.getInstance();
		cal.setTime(sqlDate);
		System.out.println("Date Information");
		System.out.println(sqlDate + "::" + sqlDate.getTime() + " :: " + cal.getTime() + " :: " + cal.getTimeInMillis()
				+ " :: " + decorate(cal));

		// JDBC driver reads by face value, applies system tz, (mutates mill
		// secs) (WRONG WAY! binding to VM)
		Timestamp sqlTS = rs.getTimestamp("tms");
		cal = Calendar.getInstance();
		cal.setTime(sqlTS);
		System.out.println("Timestamp Information from db as it is");
		System.out.println(sqlTS + "::" + sqlDate.getTime() + " :: " + cal.getTime() + " :: " + cal.getTimeInMillis()
				+ " :: " + decorate(cal));

		// JDBC driver reads by face value, applies the supplied tz that is
		// supplied (mutates mill secs) (CORRECT! reads in same Tz)
		sqlTS = rs.getTimestamp("tms", networkCal);
		cal.setTime(sqlTS);
		System.out.println("Timestamp Information read with a different Cal (allTimesInTz)");
		System.out.println(sqlTS + "::" + sqlDate.getTime() + " :: " + cal.getTime() + " :: " + cal.getTimeInMillis()
				+ " :: " + decorate(cal));
		return cal;

	}

}

 

If you are using Hibernate, You could use a user type to get similar effect.

Adventurously, I used the TimeZone.setDefault method on non-production systems of an application involving Tomcat, WebLogic a couple of wars and one ear. So far, I have not observed any issues, Google doesnot have any pages that give any known situations either. If I come to know, I will update.

分享到:
评论

相关推荐

    spring boot + mybatis + maven 自动生成Mapping

    <javaClientGenerator targetPackage="com.example.mapper" targetProject="src/main/java" type="XMLMAPPER"/> ``` 在上述配置完成后,只需运行Maven的`mybatis-generator:generate`目标,MBG就会根据配置...

    java springmvc mapping 逆向生成

    Java SpringMVC Mapping的逆向生成是一个自动化工具的使用过程,主要是为了减少手动编写XML映射文件的工作量,提高开发效率。在这个场景中,我们提到的是使用Mybatis-Generator来生成DAO(数据访问对象)、Model...

    maven+spring+springmvc+mybatis+oracle的整合,使用idea。

    MyBatis将SQL与Java代码分离,支持动态SQL,同时提供了强大的映射机制,使得ORM(Object-Relational Mapping)变得更加简单。在Spring框架中,MyBatis可以与Spring的事务管理无缝集成,通过Spring的...

    MJDU v6.0 及使用教程(注解+反射+XML+O/R Mapping+R/O Mapping)

    组件出版于 2012 年末横空出世,由于不会炒作,...我才发现原来在 2013 年时上传的 0.04 版本是不带 OR/RO Mapping 机制的。。。 想了想,还是补上 v6 这个带 OR/RO Mapping 机制的版本吧,虽然是同一时期的产物。

    java+Spring+Hibernate整合的企业OA源码

    【Hibernate】是Java中的一款对象关系映射(Object-Relational Mapping,ORM)框架,它将数据库操作与业务逻辑解耦,允许开发者通过面向对象的方式进行数据库交互。Hibernate通过XML或注解配置,可以自动映射Java类...

    Java+EE+6+API+Specifications.rar_java+EE+6....CHM

    Java EE(Java Platform, Enterprise Edition)6是Java平台在企业级应用开发中的一个关键版本,它为构建分布式、多层的Web应用程序提供了丰富的框架和API。这个API文档集是Java开发者的重要参考资料,它包含了Java ...

    Java Language to IDL Mapping Java Language to IDL Mapping

    ### Java语言到IDL映射详解 #### 一、概述 《Java语言到IDL映射》这一文档详尽地阐述了如何将Java中的分布式编程模型与OMG(Object Management Group)的IDL (Interface Definition Language)进行无缝对接。此文档...

    完美整合(通用分页)SSH+Oracle (需要自己加入jar包,只是源码)

    【SSH+Oracle 整合详解】 SSH(Struts2、Spring、Hibernate)是Java开发中常用的三大开源框架,它们各自负责Web应用的不同层面:Struts2处理MVC模式中的Controller部分,Spring作为整体的IoC(Inversion of Control...

    blog项目 java+jsp+eclipse+jdk

    【标题】"blog项目 java+jsp+eclipse+jdk"是一个基于Java技术栈的博客系统开发实例,它结合了Java后端、JSP前端、Eclipse集成开发环境以及JDK运行环境,展示了如何构建一个完整的Web应用。在这个项目中,开发者可以...

    Java+Springboot+mybatis+sharding jdbc 实现分库分表

    它允许开发者直接编写原生的SQL查询,同时还能享受到ORM(Object-Relational Mapping)带来的便利。在本项目中,MyBatis作为数据访问层,负责与数据库进行交互。 **ShardingJDBC**: ShardingSphere(原名Sharding-...

    java爬虫 Java+Elasticsearch+Kibana

    Java爬虫技术结合Elasticsearch和Kibana的综合应用是一种高效的数据抓取、存储和可视化解决方案。在本文中,我们将深入探讨这三个组件的核心概念、它们如何协同工作以及如何利用它们构建一个完整的数据处理系统。 ...

    strust2+spring3+ibatis2 +oracle10g 完整整合框架

    3. **iBatis2**:iBatis 是一个 SQL mapping 框架,它将 SQL 语句与 Java 代码分离,提供了更灵活的数据库操作方式。在 Spring3 和 iBatis2 的结合中,iBatis 负责处理数据库查询和更新,Spring 则通过 DAO(数据...

    基于java的weblogic+j2ee构建音乐网站(原代码+数据库).zip

    7. **JPA(Java Persistence API)**或Hibernate:提供ORM(Object-Relational Mapping)功能,简化数据库操作。 【WebLogic知识点】 1. **应用部署**:WebLogic支持部署各种类型的J2EE应用,如WAR、EAR文件。 2. *...

    SAP PI Java Mapping com.sap.aii.mapping.api PI MAPPING开发必须jar包

    在SAP Process Integration (PI) 中,Java Mapping是一种强大的工具,用于处理和转换数据流,以确保不同系统间的数据交换准确无误。标题提到的"com.sap.aii.mapping.api PI MAPPING开发必须jar包"是Java Mapping开发...

    Oracle9i数据类型Java数据类型Schema类型对比.doc

    - TIME: 对应 Java 的 Time 类型,但 Oracle9i 中没有单独的时间类型,通常用 DATE 类型表示。 - BLOB: 对应 Java 的 Object 类型,用于存储二进制大数据。 2. Java 数据类型: - Java 的基本数据类型如 byte, ...

    Spring.NET+NHibernate+NHibernate.Mapping.Attribute自动映射

    不喜欢NHibernate传统的*.hbm.xml来对数据库进行映射的朋友有福了,可以使用NHibernate.Mapping.Attribute.dll来实现自动映射。 减少不小的工作量。

    JAVA+Sping+Hibernater+Html5+mysql(资讯门户网站)源码

    【Hibernate】作为ORM(Object-Relational Mapping)工具,解决了Java应用程序与关系数据库之间的交互问题。它允许开发者用面向对象的方式来操作数据库,通过映射机制将Java对象与数据库表进行对应,减少了对SQL的...

    基于java的企业级应用开发:拦截器.ppt

    【基于Java的企业级应用开发:拦截器】 在Java企业级应用开发中,Spring MVC框架提供了一种名为拦截器(Interceptor)的功能,它与Servlet中的过滤器(Filter)类似,但有其独特的用法和功能。拦截器主要用于在用户...

Global site tag (gtag.js) - Google Analytics