Questions about JDBC to access the stored procedure

Recently developed an application, you need to call into a reference for the List of stored procedures.

Stored procedures: proc_test (p1 OUT Number, p2 IN Number, p3 IN TAB_CUSTOMER);

List of this type is the parameter table in a custom oracle as follows:

CREATE OR REPLACE TYPE TAB_CUSTOMER AS TABLE OF TYP_CUSTOMER;

CREATE OR REPLACE TYPE TYP_CUSTOMER AS OBJECT
(
  ID            VARCHAR2(20),
  NAME            VARCHAR2(20),
  GENDER      NUMBER,
  AGE      NUMBER,

 BIRTHDAY DATE
);

One problem: how to pass a List object to the oracle stored procedure

At first I use jpa of @Procedure, the result has been an error: the wrong type or number of parameters. I'm in the project

It defines an entity class Customer, Oracle, and the fields of the same type TYP_CUSTOMER. Passed a

List <Customer> to the stored procedure. java.util.List can not be converted into oracle.sql.ARRAY objects stored procedures needed.

Later, he consulted colleagues and relevant experience, problem solving, as follows:

[The following code to solve the problem of how to pass oracle.sql.ARRAY stored procedure]

import java.util.List;
import java.sql.Connection;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;
import oracle.sql.DATE;

/ *
    The following method returns a oracle.sql.ARRAY object with the oracle custom
    table mapping object.
    @param oracleType oracle custom class
    table @param oracleTable oracle custom class
    @list local package list data
    @return ARRAY oracle.sql.ARRAY an object that can be customized with the oracle
    object table mapping.
* /
Private ARRAY getOracleArray (CON Connection, OracleType String, String oracleTable, List <the Customer> List)
            throws Exception {
        ARRAY Array = null;
        ArrayDescriptor desc = ArrayDescriptor.createDescriptor (oracleTable, CON);
        STRUCT [] = new new structs STRUCT [List .size ()];

        if (list != null && list.size() > 0) {
            StructDescriptor structdesc = new StructDescriptor(oracleType, con);
            for (int i = 0, len = list.size(); i < len; i++) {
                Object[] result = {
                        list.get(i).getId(),
                        list.get(i).getName(),
                        list.get(i).getGender(),
                        list.get(i).getAge(),
                        new DATE(new java.sql.Date(list.get(i).getBirthday().getTime()))};
                structs[i] = new STRUCT(structdesc, con, result);
            }
            array = new ARRAY(desc, con, structs);
        } else {
            array = new ARRAY(desc, con, structs);
        }
        return array;
    }

import java.util.Date;
class Customer {
    int id;
    String name;
    String gender;
    int age;
    Date birthday;
    /* 省略getter/setter */
}

Second problem: The maximum number of connections can only be initiated connection pool request

Problem code is as follows:

@Autowired

private HikariDataSource hikariDataSource;

public void save(List<Customer> customers, int p2) {
        Connection conn = null;
        try {
            conn = getConnection();

            PreparedStatement pstmt = conn.prepareStatement("call PKG_TEST.PROC_TEST(?,?,?)");
            ARRAY p3 = getOracleArray(conn, TYP_CUSTOMER, TAB_CUSTOMER, customers);

            int p1 = 0;
            pstmt.setInt(1, p1);
            pstmt.setInt(2, p2);
            pstmt.setArray(3, p3);

            pstmt.execute();
            pstmt.close();
        } catch (SQLException e) {
            throw new PersistException(e);
        } catch (Exception e) {
            throw new PersistException(e);
        } finally {
            if(conn != null)
                try{
                    conn.close();
                }catch(Exception e){
                    throw new PersistException(e);
                }
        }
    }
    
    private Connection getConnection() {
        Connection conn = null;
        try {
            conn = hikariDataSource.getConnection();
            DatabaseMetaData metaData = conn.getMetaData();
            conn = metaData.getConnection();
        } catch (SQLException e) {
            throw new PersistException(e);
        }

        return conn;
    }

class PersistException extends RuntimeException{ /*省略*/}

I have here into a HikariDataSource, because of Hikari's Connection is not directly cast

Oracle's Connection, so did the above conversion.

It appears that after the end of a visit to the database, the database connection is not released.

Table queries can also have the same problem]

 

The code to solve the problem as follows:

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.engine.spi.SessionImplementor;

 

@PersistenceContext

private EntityManager entityManager;

    public void save(SaleRetrainingReport report) {
        try {
            Connection conn = entityManager.unwrap(SessionImplementor.class).connection();
            
            CallableStatement stmt = conn.prepareCall("call PKG_TEST.PROC_TEST(?,?,?)");
            ARRAY p3 = getOracleArray(toOracleConnection(conn), TYP_CUSTOMER, TAB_CUSTOMER, customers);

            int p1 = 0;
            stmt.setInt(1, p1);
            stmt.setInt(2, p2);
            stmt.setArray(3, p3);

            stmt.execute();
            stmt.close();
        } catch (SQLException e) {
            throw new PersistException(e);
        } catch (Exception e) {
            throw new PersistException(e);
        }
    }

    private Connection toOracleConnection(Connection connection) {
        Connection conn = null;
        try {
            DatabaseMetaData metaData = connection.getMetaData();
            conn = metaData.getConnection();
        } catch (SQLException e) {
            throw new PersistException(e);
        }

        return conn;
    }

 

 

 

 

 
--------------------- 

Guess you like

Origin www.cnblogs.com/ly570/p/10977623.html