将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.ARRAYoracle.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。 您可以这样做:

  1. 实现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 }
  2. 现在,您创建一个这些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);
  3. 最后你像往常一样叫你plsql程序: CallableStatement cs = connection.prepareCall("{call ProcedureName( ?)}"); cs.setObject(1, dataObjectArray, Types.ARRAY); cs.execute(); cs.close();

以上是关于将oracle.sql.ARRAY传递给PL / SQL过程时设置时区的主要内容,如果未能解决你的问题,请参考以下文章

oracle pl/sql 将异常类型传递给函数

将数组传递给 PostgreSQL PL/pgSQL 函数

PL/SQL:, 如何将变量传递给 SELECT 语句并返回所有结果行

每个将表名传递给过程的 ORACLE PL/SQL

将数据集合从 .NET 传递给 PL/SQL 包过程或函数?

将常规 CURSOR 传递给需要 SYS_REFCURSOR 的 PL/SQL 过程