Skip to content

executeBatch for PreparedStatement #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions jamon/src/main/java/com/jamonapi/Monitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,11 @@ public Monitor stop() {
return this;
}

public Monitor add(double value) {
public Monitor add(double value){
return add(1,value);
}

public Monitor add(int hits, double value) { //add int hits argument
if (monData.enabled) {
synchronized (monData) {
/* Being as TimeMonitors already have the current time and are passing it in the value (casted as long)
Expand All @@ -392,7 +396,7 @@ public Monitor add(double value) {
// most recent value
monData.lastValue = value;
// calculate hits i.e. n
monData.hits++;
monData.hits += hits;
// calculate total i.e. sumofX's
monData.total += value;
// used in std deviation
Expand Down
9 changes: 6 additions & 3 deletions jamon/src/main/java/com/jamonapi/MonitorComposite.java
Original file line number Diff line number Diff line change
Expand Up @@ -633,12 +633,15 @@ private MonitorImp getFirstMon() {
return (MonitorImp)monitors[0];
}



@Override
public Monitor add(double value) {
return add(1, value);
}

@Override
public Monitor add(int hits, double value) {
for (int i=0;i<numRows;i++)
monitors[i].add(value);
monitors[i].add(hits,value);

return this;
}
Expand Down
20 changes: 14 additions & 6 deletions jamon/src/main/java/com/jamonapi/proxy/JDBCMonProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwab
Object[] row=null;
SQLDeArgMon sqlMon=null;
String stackTrace="";
int hits = 1;// default 1, and change if executeBatch()
// These values need to be checked at beginning and end of routine, so need to ensure they don't change during this method call
// hence the local versions of them.
boolean isSQLSummaryEnabled=params.isSQLSummaryEnabled && params.isEnabled ;
Expand Down Expand Up @@ -84,6 +85,10 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwab

} else { // a query associated with a PreparedStatement/CallableStatement is being executed
sqlMon=(SQLDeArgMon) statementsMap.get(getMonitoredObject()); // get existing object associated with this PreparedStatement/CallableStatement
if (sqlMon == null && "executeBatch".equals(method.getName())) { // Statement with executeBatch, forbidden until implemetation of a solution
throw new UnsupportedOperationException("Doesn't support executeBatch with Statement");
}

statementReuseCounter=sqlMon.incrementCounter();// increment the reuse counter.
if (isSQLSummaryEnabled)
MonitorFactory.add("MonProxy-SQL-PreparedStatement Reuse","count", 2*statementReuseCounter);// to get the average to be accurate multiply by 2
Expand All @@ -104,7 +109,10 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwab

// Invoke the underlying method
Object returnValue=super.invoke(proxy, method, args);

if ("executeBatch".equals(method.getName())) {
hits = ((int[]) returnValue).length;
}

// If sql monitoring is not enabled or if the proxy is already there then don't wrap a proxy. For example Statements can
// return the underlying Connection which will probably already be Monitored. Note for jdbc if the Object returns another jdbc Object
// type that should be monitored it will also be monitored.
Expand Down Expand Up @@ -139,16 +147,16 @@ else if ((isSQLSummaryEnabled || isSQLDetailEnabled) && returnsPreparedStatement
if (isSQLDetailEnabled && row!=null)
row[SQL_EXECUTION_TIME_IND]=new Long(executionTime);

if (isSQLSummaryEnabled)
sqlMon.add(executionTime).appendDetails(stackTrace).stop();
if (isSQLSummaryEnabled && sqlMon != null)
sqlMon.add(hits, executionTime).appendDetails(stackTrace).stop();
}

}
}


private boolean isExecuteQueryMethod(String methodName) {
return "executeQuery".equals(methodName) || "executeUpdate".equals(methodName) || "execute".equals(methodName);
return "executeQuery".equals(methodName) || "executeUpdate".equals(methodName) || "execute".equals(methodName) || "executeBatch".equals(methodName);
}

// note i don't think this is right in that prepareCall returns a CallableStatement which inherits from PreparedStatement and so adds more methods. I
Expand Down Expand Up @@ -294,8 +302,8 @@ private SQLDeArgMon stop() {
return this;
}

private SQLDeArgMon add(double time) {
monitors.add(time);
private SQLDeArgMon add(int hits, double time) {
monitors.add(hits,time);
return this;
}

Expand Down
81 changes: 81 additions & 0 deletions jamon/src/test/java/com/jamonapi/proxy/MonProxyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.*;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;


/** Class that tests the various JAMon proxy classes via the main method */
Expand Down Expand Up @@ -373,7 +374,87 @@ private static ResultSet testPreparedStatement(Connection conn) throws Exceptio
return rs;
}

@Test
public void testSqlExecuteBatchPrepStatProxy() throws Exception {
FactoryEnabled mf = new FactoryEnabled();

Class.forName("org.hsqldb.jdbcDriver");
Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:.", "sa", "");

// returns monitored connection
MonProxyFactory.enableAll(true);
conn = MonProxyFactory.monitor(conn);

Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("create table if not exists TEST(id INTEGER)");

PreparedStatement ps = conn.prepareStatement("update TEST set id=? WHERE id=?");
ps.setInt(1, 1);
ps.setInt(2, 1);
ps.addBatch();
ps.setInt(1, 2);
ps.setInt(2, 3);
ps.addBatch();
ps.setInt(1, 2);
ps.setInt(2, 3);
ps.addBatch();

int[] executeBatchPS = ps.executeBatch();


// to get the following keys
// for (int i=0; i< MonitorFactory.getMap().keySet().toArray().length;i++) {
// System.out.println( MonitorFactory.getMap().keySet().toArray()[i] );
// }
// System.out.println(" ");
//
// JAMon Label=MonProxy-SQL-Type: create, Units=ms.
// JAMon Label=MonProxy-SQL-Type: update, Units=ms.
// JAMon Label=MonProxy-SQL-PreparedStatement: update TEST set id=? WHERE id=?, Units=ms.
// JAMon Label=MonProxy-SQL-PreparedStatement Reuse, Units=count
// JAMon Label=MonProxy-Interface (class=org.hsqldb.jdbc.JDBCPreparedStatement): public abstract void java.sql.PreparedStatement.addBatch() throws java.sql.SQLException, Units=ms.
// JAMon Label=MonProxy-Interface (class=org.hsqldb.jdbc.JDBCPreparedStatement): public abstract void java.sql.PreparedStatement.setInt(int,int) throws java.sql.SQLException, Units=ms.
// JAMon Label=MonProxy-SQL-Type: All, Units=ms.
// JAMon Label=MonProxy-Interface (class=org.hsqldb.jdbc.JDBCConnection): public abstract java.sql.PreparedStatement java.sql.Connection.prepareStatement(java.lang.String) throws java.sql.SQLException, Units=ms.
// JAMon Label=MonProxy-Interface (class=org.hsqldb.jdbc.JDBCStatement): public abstract java.sql.ResultSet java.sql.Statement.executeQuery(java.lang.String) throws java.sql.SQLException, Units=ms.
// JAMon Label=MonProxy-Interface (class=org.hsqldb.jdbc.JDBCConnection): public abstract java.sql.Statement java.sql.Connection.createStatement() throws java.sql.SQLException, Units=ms.
// JAMon Label=com.jamonapi.Exceptions, Units=Exception
// JAMon Label=MonProxy-Interface (class=org.hsqldb.jdbc.JDBCPreparedStatement): public abstract int[] java.sql.Statement.executeBatch() throws java.sql.SQLException, Units=ms.
// JAMon Label=MonProxy-SQL-Statement: create table if not exists TEST(id INTEGER), Units=ms.


assertEquals(3,executeBatchPS.length);
assertEquals((int) MonitorFactory.getMonitor("MonProxy-SQL-PreparedStatement: update TEST set id=? WHERE id=?", "ms.").getHits(),executeBatchPS.length);
assertEquals((int) MonitorFactory.getMonitor("MonProxy-SQL-Type: update", "ms.").getHits(),executeBatchPS.length);
}

@Test(expected = UnsupportedOperationException.class)
public void testSqlExecuteBatchStatementProxy() throws Exception {
int times = 2000;
Params params = new Params();
FactoryEnabled mf = new FactoryEnabled();

Class.forName("org.hsqldb.jdbcDriver");
Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:.", "sa", "");

// returns monitored connection
MonProxyFactory.enableAll(true);
conn = MonProxyFactory.monitor(conn);

//mainTestMethod("MonProxyFactory defaults first time", conn, times, params, mf);

Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("create table if not exists TEST(id INTEGER)");

Statement statement = conn.createStatement();
statement.addBatch("update TEST set id=21 WHERE id=10");
statement.addBatch("update TEST set id=22 WHERE id=11");
statement.addBatch("update TEST set id=23 WHERE id=12");
statement.addBatch("update TEST set id=24 WHERE id=13");

int[] executeBatchSt = statement.executeBatch(); //doit lever UnsupportedOperationException car cette version de JAMon ne traite pas les Batchs avec Statement
}

private static void throwException(Connection conn) {
try {
Statement st = conn.createStatement();
Expand Down