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;
}
---------------------