当前位置: 首页 > 面试题库 >

Java-如何使用自定义类型调用oracle过程?

翟曦
2023-03-14
问题内容

我有一个plsql程序

PROCEDURE merge_time_bounds(s1_bd_t IN bd_tb_struct, s2_bd_t IN bd_tb_struct, r_bd_t OUT bd_tb_struct);

我尝试在Java代码中调用它。我已经使用其他过程执行了所有参数均为VARCHAR类型的过程,但是这里所有参数都是“ bd_tb_struct”

create or replace TYPE bd_tb_struct FORCE
AS
OBJECT
(
start_ts   TIMESTAMP (3) ,
end_ts     TIMESTAMP (3) ,
time_type  NUMBER (19) ,
duration   NUMBER (12) ) FINAL ;

我也有一个带有此Comment的Java类。“数据库中对应类型的类。(bd_tb_struct)”

BoundsSqlType.java

有人可以解释一下我该如何称呼我的程序吗?


问题答案:

Oracle安装程序

CREATE OR REPLACE TYPE BD_TB_STRUCT AS OBJECT(
  start_ts TIMESTAMP(3),
  end_ts   TIMESTAMP(3),
  time_type NUMBER(19),
  duration NUMBER(12)
) FINAL;
/

CREATE OR REPLACE PROCEDURE merge_time_bounds(
  s1_bd_t IN  bd_tb_struct,
  s2_bd_t IN  bd_tb_struct,
  r_bd_t  OUT bd_tb_struct
)
IS
  p_start TIMESTAMP(3) := LEAST(    s1_bd_t.start_ts,  s2_bd_t.start_ts );
  p_end   TIMESTAMP(3) := GREATEST( s1_bd_t.end_ts,    s2_bd_t.end_ts );
BEGIN
  r_bd_t := new BD_TB_STRUCT( 
                  p_start,
                  p_end,
                  COALESCE( s1_bd_t.time_type, s2_bd_t.time_type ),
                  ( CAST( p_end AS DATE ) - CAST( p_start AS DATE ) ) * 24 * 60 * 60
                );
END;
/

Java SQLData类

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

public class BoundsSQL implements SQLData
{
  public static final String SQL_TYPE = "BD_TB_STRUCT";
  public java.sql.Timestamp start;
  public java.sql.Timestamp end;
  public BigInteger type;
  public BigInteger duration;

  public BoundsSQL()
  {
  }

  public BoundsSQL(
      final int year,
      final int month,
      final int dayOfMonth,
      final int hour,
      final int minute,
      final int seconds,
      final long duration,
      final long type )
  {
    final long epochSeconds = LocalDateTime.of(
        year,
        month,
        dayOfMonth,
        hour,
        minute,
        seconds
      ).toEpochSecond( ZoneOffset.UTC );
    this.start    = new Timestamp( epochSeconds * 1000 );
    this.end      = new Timestamp( (epochSeconds + duration) * 1000 );
    this.duration = BigInteger.valueOf( duration );
    this.type = BigInteger.valueOf( type );
  }

  @Override
  public String getSQLTypeName() throws SQLException
  {
    return SQL_TYPE;
  }

  @Override
  public void readSQL( SQLInput stream,
      String typeName ) throws SQLException
  {
    start    = stream.readTimestamp();
    end      = stream.readTimestamp();
    type     = stream.readBigDecimal().toBigInteger();
    duration = stream.readBigDecimal().toBigInteger();
  }

  @Override
  public void writeSQL( SQLOutput stream ) throws SQLException
  {
    stream.writeTimestamp( start );
    stream.writeTimestamp( end );
    stream.writeBigDecimal( new BigDecimal( type ) );
    stream.writeBigDecimal( new BigDecimal( duration ) );
  }

  @Override
  public String toString()
  {
    return String.format(
        "Start:    %s\nEnd:      %s\nDuration: %s\nType:     %s",
        start,
        end,
        duration,
        type
    );
  }
}

从Java调用存储过程

使用调用存储过程OracleCallableStatement#setObject( int, Object )以传递参数,并将类放入类型映射中,并使用OracleCallableStatement#registerOutParameter( int, int, string )OracleCallableStatement#getObject( int )检索参数。

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Map;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleTypes;

public class PassStructToProcedure
{

  public static void main( final String[] args ){
    OracleConnection con = null;
    try{
      Class.forName( "oracle.jdbc.OracleDriver" );

      con = (OracleConnection) DriverManager.getConnection(
          "jdbc:oracle:thin:@localhost:1521:orcl",
          "USERNAME",
          "PASSWORD"
      );

      BoundsSQL bound1 = new BoundsSQL( 2019, 1, 1, 0, 0, 0, 10, 1 );
      BoundsSQL bound2 = new BoundsSQL( 2019, 1, 1, 0, 0, 5, 10, 2 );

      OracleCallableStatement st = (OracleCallableStatement) con.prepareCall(
          "{ call MERGE_TIME_BOUNDS( ?, ?, ? ) }"
      );

      st.setObject( 1, bound1 );
      st.setObject( 2, bound2 );
      st.registerOutParameter( 3, OracleTypes.STRUCT, BoundsSQL.SQL_TYPE );
      st.execute();

      Map<String,Class<?>> typeMap = con.getTypeMap();
      typeMap.put( BoundsSQL.SQL_TYPE, BoundsSQL.class );

      BoundsSQL out = (BoundsSQL) st.getObject( 3 );

      System.out.println( out.toString() );

      st.close();
    } catch (ClassNotFoundException | SQLException ex) {
      System.out.println( ex.getMessage() );
      ex.printStackTrace();
    } finally {
      try{
        if ( con != null )
          con.close();
      }
      catch( SQLException e )
      {

      }
    }
  }
}

输出

Start:    2019-01-01 00:00:00.0
End:      2019-01-01 00:00:15.0
Duration: 15
Type:     1


 类似资料:
  • 问题内容: 在Oracle DB中: 我有以下存储过程: 类型IDS_TABLE是: 如何在Java中调用getInfo? 问题答案: 手动设置Oracle SQL对象和java对象之间的链接不是一件容易的事。特别是,从用户定义对象的数组(或嵌套表)到Java到Oracle的传递比标准数据类型的数组更复杂。换句话说,调用带有签名的过程会更容易: 而不是签名为: 你可以在过程周​​围编写包装器,以将

  • 问题内容: 我想将非spring bean类对象用作球衣Web服务类方法的参数。但是它在构建时会给出缺少的依赖项错误。 我的代码是: 问题答案: 关键是路径参数以字符串形式出现。根据规范,如果我们希望将自定义类型作为注入,则自定义类应具有以下三项之一: 返回类型的公共静态 返回类型的公共静态 或接受字符串的公共构造函数 另一种选择实现。您可以在此处查看示例。 如果您不拥有该类(它是无法更改的第三方

  • 问题是我写了简单的注释处理器,它根本不处理类型注释。simple annotations processor的源代码如下所示: 有什么想法如何使用或如何通过SimpleAnnotationsProcessor访问类型注释吗?使用可插入的注释处理API对我来说是不必要的,我认为它会比Java反射有更好的性能。无论如何,我也不知道如何通过Java反射访问类型注释。

  • 问题内容: 我正在编写一些JDBC代码,该代码调用具有“自定义对象”返回类型的Oracle 11g PL / SQL过程。每当我尝试使用返回类型的寄存器时,根据所设置的类型执行该语句时,都会收到ORA-03115或PLS-00306错误。下面是一个示例: PLSQL代码: 更多PLSQL代码(自定义对象详细信息): Java代码: 谁能给我一个例子,说明我该怎么做?我想有可能。但是我看不到行集Or

  • 现在,问题是,虽然我可以获得存储过程返回的结果,但该结果没有转换为Java类(TNapraviNalog),所以我必须手动执行此操作。我可以用TNapraviNalog的实例(stmt.SetObject(1,ParamValues.get(0));)成功调用Oracle过程,但无法将结果转换为TNapraviNalog。我真的很想有一个 但是,这一行会导致异常(java.lang.ClassCa

  • 问题内容: 实施自己的最佳方法是哪一种? 其实我得到一个问题登记。如果我在中使用自定义类,则管理页面上不会显示任何应用程序。 我用一个小技巧解决了这个问题。我写了这个课: 并像这样实现我的自定义AdminSite: 所以,我可以用这个为。 有人知道更好的方法吗?由于我以下划线开头访问var,所以它不过是hack。我不喜欢黑客。 编辑:另一种方法是重写函数,但是在这种情况下,我将有冗余代码。 问题答