@Test public void testOperationWithDirectCloseCall() throws SQLException { Connection con = createMock(Connection.class); DataSource ds = createMock(DataSource.class); expect(ds.getConnection()).andReturn(con); // con1 con.close(); expect(ds.getConnection()).andReturn(con); // con2 con.close(); replay(ds); replay(con); final ExtendedConnectionDataSourceProxy csds = new ExtendedConnectionDataSourceProxy(ds); Connection con1 = csds.getConnection(); csds.startCloseSuppression(con1); Connection con1_1 = csds.getConnection(); assertSame("should be same connection", con1_1, con1); con1_1.close(); // no mock call for this - should be suppressed Connection con1_2 = csds.getConnection(); assertSame("should be same connection", con1_2, con1); Connection con2 = csds.getConnection(); assertNotSame("shouldn't be same connection", con2, con1); csds.stopCloseSuppression(con1); assertTrue("should be able to close connection", csds.shouldClose(con1)); con1_1 = null; con1_2 = null; con1.close(); assertTrue("should be able to close connection", csds.shouldClose(con2)); con2.close(); verify(ds); verify(con); }
@Test public void testSupressOfCloseWithJdbcTemplate() throws Exception { Connection con = createMock(Connection.class); DataSource ds = createMock(DataSource.class); Statement stmt = createMock(Statement.class); ResultSet rs = createMock(ResultSet.class); // open and start suppressing close expect(ds.getConnection()).andReturn(con); // transaction 1 expect(con.getAutoCommit()).andReturn(false); expect(con.createStatement()).andReturn(stmt); expect(stmt.executeQuery("select baz from bar")).andReturn(rs); expect(rs.next()).andReturn(false); expect(con.createStatement()).andReturn(stmt); expect(stmt.executeQuery("select foo from bar")).andReturn(rs); expect(rs.next()).andReturn(false); con.commit(); // transaction 2 expect(con.getAutoCommit()).andReturn(false); expect(con.createStatement()).andReturn(stmt); expect(stmt.executeQuery("select ham from foo")).andReturn(rs); expect(rs.next()).andReturn(false); // REQUIRES_NEW transaction expect(ds.getConnection()).andReturn(con); expect(con.getAutoCommit()).andReturn(false); expect(con.createStatement()).andReturn(stmt); expect(stmt.executeQuery("select 1 from eggs")).andReturn(rs); expect(rs.next()).andReturn(false); con.commit(); con.close(); // resume transaction 2 expect(con.createStatement()).andReturn(stmt); expect(stmt.executeQuery("select more, ham from foo")).andReturn(rs); expect(rs.next()).andReturn(false); con.commit(); // transaction 3 expect(con.getAutoCommit()).andReturn(false); expect(con.createStatement()).andReturn(stmt); expect(stmt.executeQuery("select spam from ham")).andReturn(rs); expect(rs.next()).andReturn(false); con.commit(); // stop suppressing close and close con.close(); // standalone query expect(ds.getConnection()).andReturn(con); expect(con.createStatement()).andReturn(stmt); expect(stmt.executeQuery("select egg from bar")).andReturn(rs); expect(rs.next()).andReturn(false); con.close(); replay(rs); replay(stmt); replay(con); replay(ds); final ExtendedConnectionDataSourceProxy csds = new ExtendedConnectionDataSourceProxy(); csds.setDataSource(ds); PlatformTransactionManager tm = new DataSourceTransactionManager(csds); TransactionTemplate tt = new TransactionTemplate(tm); final TransactionTemplate tt2 = new TransactionTemplate(tm); tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); final JdbcTemplate template = new JdbcTemplate(csds); Connection connection = DataSourceUtils.getConnection(csds); csds.startCloseSuppression(connection); tt.execute( new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { template.queryForList("select baz from bar"); template.queryForList("select foo from bar"); return null; } }); tt.execute( new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { template.queryForList("select ham from foo"); tt2.execute( new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { template.queryForList("select 1 from eggs"); return null; } }); template.queryForList("select more, ham from foo"); return null; } }); tt.execute( new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { template.queryForList("select spam from ham"); return null; } }); csds.stopCloseSuppression(connection); DataSourceUtils.releaseConnection(connection, csds); template.queryForList("select egg from bar"); verify(rs); verify(stmt); verify(con); verify(ds); }