将oracle.sql.ARRAY传递给PL / SQL过程时设置时区
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将oracle.sql.ARRAY传递给PL / SQL过程时设置时区相关的知识,希望对你有一定的参考价值。
我正在用Java调用plsql package procedure
。此过程有一个带有timestamp
的类型参数。当我将一个timestamp参数直接设置到一个过程时,我可以指定一个Calendar object
来声明使用e的时区。 G。
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
statement.setTimestamp(1, new Timestamp(calendar.getTimeInMillis()), calendar);
有没有办法在使用oracle.sql.ARRAY
或oracle.sql.STRUCT
时声明时区?
使用的类型声明如下:
CREATE OR REPLACE TYPE "TY_EVENT_OBJECT"
AS
OBJECT
(
timestamp_event date,
state number(15),
parameter_name varchar2(248),
value number(15)
);
CREATE OR REPLACE TYPE "TY_EVENTS"
AS
TABLE OF TY_EVENT_OBJECT;
TY_EVENTS类型是我必须使用的plsql过程的一个参数。
答案
当您使用用户定义的oracle类型时,无法简单地传递将用于时区转换的日历。当使用oracle.sql.ARRAY和oracle.sql.STRUCT时,ojdbc使用本地日历将java.sql.Date转换为oracle.sql.DATE,因此在您的情况下,存储在数据库中的实际日期是没有时区的本地时间。 因此,如果您希望将日期存储到UTC中的数据库,则必须使用UTC日历手动将java.sql.Date转换为oracle.sql.DATE。 您可以这样做:
- 实现SQLData接口并覆盖方法。
注意:
-getSQLTypeName必须返回数据库中定义的实际类型名称,否则不起作用。
- 我们在下面使用java.sql.Date,这很重要。所以,如果你想在TyEventObject之外的java.util.Date你可以创建一个执行转换的setter / getter
public class TyEventObject implements SQLData { private String sqlTypeName = "TY_EVENT_OBJECT"; private java.sql.Date timestampEvent; private long state; private String parameterName; private long value; @Override public String getSQLTypeName() throws SQLException { return sqlTypeName; } @Override public void readSQL(SQLInput stream, String typeName) throws SQLException { sqlTypeName = typeName; // Reading date in UTC time OracleJdbc2SQLInput oracleStream = (OracleJdbc2SQLInput) stream; DATE oracleDate = (DATE)oracleStream.readOracleObject(); if( oracleDate != null) { timestampEvent = oracleDate.dateValue( Calendar.getInstance(TimeZone.getTimeZone("UTC"))); } else { timestampEvent = null; } state = stream.readLong(); parameterName = stream.readString(); value = stream.readLong(); } @Override public void writeSQL(SQLOutput stream) throws SQLException { // Writing timestamp in UTC time OracleSQLOutput oracleStream = (OracleSQLOutput) stream; if( timestampEvent != null) { DATE oracleDate = new DATE( timestampEvent, Calendar.getInstance(TimeZone.getTimeZone("UTC"))); oracleStream.writeOracleObject( oracleDate); } else { stream.writeDate( null); } stream.writeLong( state); stream.writeString( parameterName); stream.writeLong( value); } // add public getters and setters }
- 现在,您创建一个这些TyEventObject对象的数组,以传递给plsql过程(请注意,Array是java.sql.Array):
// I assume that your event objects that you want to save are in the list eventObjects TyEventObject[] entries = new TyEventObject[ eventObjects.size()]; for( int i=0; i < eventObjects.size(); i++) { entries[i] = new TyEventObject(); // You set the properties here // entries[i].setTimestampEvent( eventObjects.get( i).getTimestampEvent()); } Array dataObjectArray = connection.createArrayOf( "TY_EVENTS", entries);
- 最后你像往常一样叫你plsql程序:
CallableStatement cs = connection.prepareCall("{call ProcedureName( ?)}"); cs.setObject(1, dataObjectArray, Types.ARRAY); cs.execute(); cs.close();
以上是关于将oracle.sql.ARRAY传递给PL / SQL过程时设置时区的主要内容,如果未能解决你的问题,请参考以下文章
PL/SQL:, 如何将变量传递给 SELECT 语句并返回所有结果行