IDEMPIERE-5509 Implement readonly query with using Trx (#1599)

This commit is contained in:
hengsin 2022-12-05 23:48:23 +08:00 committed by GitHub
parent 8cf16e9fbd
commit 8ab72bcba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 194 additions and 72 deletions

View File

@ -45,6 +45,17 @@ public class PreparedStatementProxy extends StatementProxy {
init(); init();
} // PreparedStatementProxy } // PreparedStatementProxy
public PreparedStatementProxy(int resultSetType, int resultSetConcurrency,
String sql0, Connection connection) {
if (sql0 == null || sql0.length() == 0)
throw new IllegalArgumentException("sql required");
p_vo = new CStatementVO(resultSetType, resultSetConcurrency, DB
.getDatabase().convertStatement(sql0));
init(connection);
} // PreparedStatementProxy
public PreparedStatementProxy(CStatementVO vo) public PreparedStatementProxy(CStatementVO vo)
{ {
super(vo); super(vo);
@ -74,6 +85,19 @@ public class PreparedStatementProxy extends StatementProxy {
} }
} }
/**
* Initialise the prepared statement wrapper object
*/
protected void init(Connection connection) {
try {
p_stmt = connection.prepareStatement(p_vo.getSql(), p_vo
.getResultSetType(), p_vo.getResultSetConcurrency());
} catch (Exception e) {
log.log(Level.SEVERE, p_vo.getSql(), e);
throw new DBException(e);
}
}
@Override @Override
protected RowSet getRowSet() protected RowSet getRowSet()
{ {

View File

@ -13,6 +13,7 @@
package org.compiere.db; package org.compiere.db;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.sql.Connection;
import org.compiere.util.CCallableStatement; import org.compiere.util.CCallableStatement;
import org.compiere.util.CPreparedStatement; import org.compiere.util.CPreparedStatement;
@ -56,6 +57,21 @@ public class ProxyFactory {
new PreparedStatementProxy(resultSetType, resultSetConcurrency, sql, trxName)); new PreparedStatementProxy(resultSetType, resultSetConcurrency, sql, trxName));
} }
/**
*
* @param resultSetType
* @param resultSetConcurrency
* @param sql
* @param trxName
* @return CPreparedStatement proxy
*/
public static CPreparedStatement newCPreparedStatement(int resultSetType,
int resultSetConcurrency, String sql, Connection connection) {
return (CPreparedStatement)Proxy.newProxyInstance(CPreparedStatement.class.getClassLoader(),
new Class[]{CPreparedStatement.class},
new PreparedStatementProxy(resultSetType, resultSetConcurrency, sql, connection));
}
/** /**
* *
* @param resultSetType * @param resultSetType

View File

@ -711,6 +711,17 @@ public final class DB
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, trxName); return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, trxName);
} // prepareStatement } // prepareStatement
/**
* Prepare Statement
* @param sql
* @param trxName transaction
* @return Prepared Statement
*/
public static CPreparedStatement prepareStatement (Connection connection, String sql)
{
return prepareStatement(connection, sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
} // prepareStatement
/** /**
* Prepare Statement. * Prepare Statement.
* @param sql * @param sql
@ -742,6 +753,23 @@ public final class DB
return ProxyFactory.newCPreparedStatement(resultSetType, resultSetConcurrency, sql, trxName); return ProxyFactory.newCPreparedStatement(resultSetType, resultSetConcurrency, sql, trxName);
} // prepareStatement } // prepareStatement
/**
* Prepare Statement.
* @param sql sql statement
* @param resultSetType - ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE
* @param resultSetConcurrency - ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
* @param trxName transaction name
* @return Prepared Statement r/o or r/w depending on concur
*/
public static CPreparedStatement prepareStatement(Connection connection, String sql,
int resultSetType, int resultSetConcurrency)
{
if (sql == null || sql.length() == 0)
throw new IllegalArgumentException("No SQL");
//
return ProxyFactory.newCPreparedStatement(resultSetType, resultSetConcurrency, sql, connection);
} // prepareStatement
/** /**
* Create Read Only Statement * Create Read Only Statement
* @return Statement * @return Statement
@ -1242,18 +1270,20 @@ public final class DB
int retValue = -1; int retValue = -1;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
Trx trx = null; Connection conn = null;
if (trxName == null) if (trxName == null)
{ conn = DB.createConnection(true, Connection.TRANSACTION_READ_COMMITTED);
trxName = Trx.createTrxName("getSQLValueEx");
trx = Trx.get(trxName, true);
}
try try
{ {
if (trx != null) if (conn != null)
{ {
trx.getConnection().setReadOnly(true); conn.setAutoCommit(false);
conn.setReadOnly(true);
} }
if (conn != null)
pstmt = prepareStatement(conn, sql);
else
pstmt = prepareStatement(sql, trxName); pstmt = prepareStatement(sql, trxName);
setParameters(pstmt, params); setParameters(pstmt, params);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
@ -1264,9 +1294,13 @@ public final class DB
} }
catch (SQLException e) catch (SQLException e)
{ {
if (trx != null) if (conn != null)
{ {
trx.rollback(); try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} }
throw new DBException(e, sql); throw new DBException(e, sql);
} }
@ -1274,14 +1308,32 @@ public final class DB
{ {
close(rs, pstmt); close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
if (trx != null) if (conn != null)
{ {
trx.close(); closeAndResetReadonlyConnection(conn);
} }
} }
return retValue; return retValue;
} }
private static void closeAndResetReadonlyConnection(Connection conn) {
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.setReadOnly(false);
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/** /**
* Get String Value from sql * Get String Value from sql
* @param trxName optional transaction name * @param trxName optional transaction name
@ -1341,18 +1393,20 @@ public final class DB
String retValue = null; String retValue = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
Trx trx = null; Connection conn = null;
if (trxName == null) if (trxName == null)
{ conn = DB.createConnection(true, Connection.TRANSACTION_READ_COMMITTED);
trxName = Trx.createTrxName("getSQLValueEx");
trx = Trx.get(trxName, true);
}
try try
{ {
if (trx != null) if (conn != null)
{ {
trx.getConnection().setReadOnly(true); conn.setAutoCommit(false);
conn.setReadOnly(true);
} }
if (conn != null)
pstmt = prepareStatement(conn, sql);
else
pstmt = prepareStatement(sql, trxName); pstmt = prepareStatement(sql, trxName);
setParameters(pstmt, params); setParameters(pstmt, params);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
@ -1363,9 +1417,13 @@ public final class DB
} }
catch (SQLException e) catch (SQLException e)
{ {
if (trx != null) if (conn != null)
{ {
trx.rollback(); try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} }
throw new DBException(e, sql); throw new DBException(e, sql);
} }
@ -1373,9 +1431,9 @@ public final class DB
{ {
close(rs, pstmt); close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
if (trx != null) if (conn != null)
{ {
trx.close(); closeAndResetReadonlyConnection(conn);
} }
} }
return retValue; return retValue;
@ -1440,18 +1498,20 @@ public final class DB
BigDecimal retValue = null; BigDecimal retValue = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
Trx trx = null; Connection conn = null;
if (trxName == null) if (trxName == null)
{ conn = DB.createConnection(true, Connection.TRANSACTION_READ_COMMITTED);
trxName = Trx.createTrxName("getSQLValueEx");
trx = Trx.get(trxName, true);
}
try try
{ {
if (trx != null) if (conn != null)
{ {
trx.getConnection().setReadOnly(true); conn.setAutoCommit(false);
conn.setReadOnly(true);
} }
if (conn != null)
pstmt = prepareStatement(conn, sql);
else
pstmt = prepareStatement(sql, trxName); pstmt = prepareStatement(sql, trxName);
setParameters(pstmt, params); setParameters(pstmt, params);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
@ -1462,9 +1522,13 @@ public final class DB
} }
catch (SQLException e) catch (SQLException e)
{ {
if (trx != null) if (conn != null)
{ {
trx.rollback(); try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} }
throw new DBException(e, sql); throw new DBException(e, sql);
} }
@ -1472,9 +1536,9 @@ public final class DB
{ {
close(rs, pstmt); close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
if (trx != null) if (conn != null)
{ {
trx.close(); closeAndResetReadonlyConnection(conn);
} }
} }
return retValue; return retValue;
@ -1540,18 +1604,20 @@ public final class DB
Timestamp retValue = null; Timestamp retValue = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
Trx trx = null; Connection conn = null;
if (trxName == null) if (trxName == null)
{ conn = DB.createConnection(true, Connection.TRANSACTION_READ_COMMITTED);
trxName = Trx.createTrxName("getSQLValueEx");
trx = Trx.get(trxName, true);
}
try try
{ {
if (trx != null) if (conn != null)
{ {
trx.getConnection().setReadOnly(true); conn.setAutoCommit(false);
conn.setReadOnly(true);
} }
if (conn != null)
pstmt = prepareStatement(conn, sql);
else
pstmt = prepareStatement(sql, trxName); pstmt = prepareStatement(sql, trxName);
setParameters(pstmt, params); setParameters(pstmt, params);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
@ -1562,9 +1628,13 @@ public final class DB
} }
catch (SQLException e) catch (SQLException e)
{ {
if (trx != null) if (conn != null)
{ {
trx.rollback(); try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} }
throw new DBException(e, sql); throw new DBException(e, sql);
} }
@ -1572,9 +1642,9 @@ public final class DB
{ {
close(rs, pstmt); close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
if (trx != null) if (conn != null)
{ {
trx.close(); closeAndResetReadonlyConnection(conn);
} }
} }
return retValue; return retValue;
@ -2455,18 +2525,20 @@ public final class DB
List<Object> retValue = new ArrayList<Object>(); List<Object> retValue = new ArrayList<Object>();
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
Trx trx = null; Connection conn = null;
if (trxName == null) if (trxName == null)
{ conn = DB.createConnection(true, Connection.TRANSACTION_READ_COMMITTED);
trxName = Trx.createTrxName("getSQLValueObjectsEx");
trx = Trx.get(trxName, true);
}
try try
{ {
if (trx != null) if (conn != null)
{ {
trx.getConnection().setReadOnly(true); conn.setAutoCommit(false);
conn.setReadOnly(true);
} }
if (conn != null)
pstmt = prepareStatement(conn, sql);
else
pstmt = prepareStatement(sql, trxName); pstmt = prepareStatement(sql, trxName);
setParameters(pstmt, params); setParameters(pstmt, params);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
@ -2485,9 +2557,13 @@ public final class DB
} }
catch (SQLException e) catch (SQLException e)
{ {
if (trx != null) if (conn != null)
{ {
trx.rollback(); try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} }
throw new DBException(e, sql); throw new DBException(e, sql);
} }
@ -2495,9 +2571,9 @@ public final class DB
{ {
close(rs, pstmt); close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
if (trx != null) if (conn != null)
{ {
trx.close(); closeAndResetReadonlyConnection(conn);
} }
} }
return retValue; return retValue;
@ -2516,18 +2592,20 @@ public final class DB
List<List<Object>> rowsArray = new ArrayList<List<Object>>(); List<List<Object>> rowsArray = new ArrayList<List<Object>>();
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
Trx trx = null; Connection conn = null;
if (trxName == null) if (trxName == null)
{ conn = DB.createConnection(true, Connection.TRANSACTION_READ_COMMITTED);
trxName = Trx.createTrxName("getSQLArrayObjectsEx");
trx = Trx.get(trxName, true);
}
try try
{ {
if (trx != null) if (conn != null)
{ {
trx.getConnection().setReadOnly(true); conn.setAutoCommit(false);
conn.setReadOnly(true);
} }
if (conn != null)
pstmt = prepareStatement(conn, sql);
else
pstmt = prepareStatement(sql, trxName); pstmt = prepareStatement(sql, trxName);
setParameters(pstmt, params); setParameters(pstmt, params);
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
@ -2546,9 +2624,13 @@ public final class DB
} }
catch (SQLException e) catch (SQLException e)
{ {
if (trx != null) if (conn != null)
{ {
trx.rollback(); try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} }
throw new DBException(e, sql); throw new DBException(e, sql);
} }
@ -2556,9 +2638,9 @@ public final class DB
{ {
close(rs, pstmt); close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
if (trx != null) if (conn != null)
{ {
trx.close(); closeAndResetReadonlyConnection(conn);
} }
} }
if (rowsArray.size() == 0) if (rowsArray.size() == 0)