/** * Tests with a test with transaction rollback configured */ @Test public void testRollback() throws Exception { expect(mockConnection1.getAutoCommit()).andReturn(true).andReturn(false).anyTimes(); mockConnection1.setAutoCommit(false); mockConnection1.rollback(); mockConnection1.close(); replay(mockConnection1, mockConnection2); Method testMethod = RollbackTest.class.getMethod("test", new Class[]{}); DataSource dataSource = wrapper.getTransactionalDataSourceAndActivateTransactionIfNeeded(rollbackTest); databaseModule.startTransactionForTestMethod(rollbackTest, testMethod); Connection connection1 = dataSource.getConnection(); Connection targetConnection1 = ((ConnectionProxy) connection1).getTargetConnection(); connection1.close(); Connection connection2 = dataSource.getConnection(); Connection targetConnection2 = ((ConnectionProxy) connection2).getTargetConnection(); connection2.close(); assertSame(targetConnection1, targetConnection2); databaseModule.endTransactionForTestMethod(rollbackTest, testMethod); verify(mockConnection1, mockConnection2); }
/** * Tests with a test with transaction commit configured */ @Test public void testCommit() throws Exception { expect(mockConnection1.getAutoCommit()).andReturn(true).andReturn(false).anyTimes(); mockConnection1.setAutoCommit(false); mockConnection1.commit(); mockConnection1.close(); replay(mockConnection1, mockConnection2); Method testMethod = CommitTest.class.getMethod("test", new Class[]{}); DataSource dataSource = wrapper.getTransactionalDataSourceAndActivateTransactionIfNeeded(commitTest); databaseModule.startTransactionForTestMethod(commitTest, testMethod); Connection connection1 = dataSource.getConnection(); Connection targetConnection1 = ((ConnectionProxy) connection1).getTargetConnection(); connection1.close(); Connection connection2 = dataSource.getConnection(); Connection targetConnection2 = ((ConnectionProxy) connection2).getTargetConnection(); connection2.close(); assertSame(targetConnection1, targetConnection2); databaseModule.endTransactionForTestMethod(commitTest, testMethod); verify(mockConnection1, mockConnection2); }
@Test public void getConnection_NoReadReplicaAvailableNoTransactionActive_returnsDefaultDataSource() throws Exception { //Arrange DataSource defaultDataSource = mock(DataSource.class); Connection connection = mock(Connection.class); when(defaultDataSource.getConnection()).thenReturn(connection); ReadOnlyRoutingDataSource readOnlyRoutingDataSource = new ReadOnlyRoutingDataSource(); readOnlyRoutingDataSource.setTargetDataSources(Collections.emptyMap()); readOnlyRoutingDataSource.setDefaultTargetDataSource(defaultDataSource); readOnlyRoutingDataSource.afterPropertiesSet(); LazyConnectionDataSourceProxy dataSource = new LazyConnectionDataSourceProxy(readOnlyRoutingDataSource); //Act Connection connectionReturned = dataSource.getConnection(); //Assert assertSame(connection, ((ConnectionProxy) connectionReturned).getTargetConnection()); }
@Test public void getConnection_NoReadReplicaAvailableReadOnlyTransactionActive_returnsDefaultDataSource() throws Exception { //Arrange DataSource defaultDataSource = mock(DataSource.class); Connection connection = mock(Connection.class); when(defaultDataSource.getConnection()).thenReturn(connection); ReadOnlyRoutingDataSource readOnlyRoutingDataSource = new ReadOnlyRoutingDataSource(); readOnlyRoutingDataSource.setTargetDataSources(Collections.emptyMap()); readOnlyRoutingDataSource.setDefaultTargetDataSource(defaultDataSource); readOnlyRoutingDataSource.afterPropertiesSet(); LazyConnectionDataSourceProxy dataSource = new LazyConnectionDataSourceProxy(readOnlyRoutingDataSource); DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); transactionDefinition.setReadOnly(true); TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource), transactionDefinition); //Act Connection connectionReturned = transactionTemplate.execute(status -> { try { return ((ConnectionProxy) dataSource.getConnection()).getTargetConnection(); } catch (SQLException e) { fail(e.getMessage()); } return null; }); //Assert assertSame(connection, connectionReturned); }
@Test public void getConnection_ReadReplicaAvailableReadOnlyTransactionActive_returnsReadReplicaDataSource() throws Exception { //Arrange DataSource defaultDataSource = mock(DataSource.class); Connection connection = mock(Connection.class); DataSource readOnlyDataSource = mock(DataSource.class); Connection readOnlyConnection = mock(Connection.class); when(readOnlyDataSource.getConnection()).thenReturn(readOnlyConnection); when(defaultDataSource.getConnection()).thenReturn(connection); ReadOnlyRoutingDataSource readOnlyRoutingDataSource = new ReadOnlyRoutingDataSource(); readOnlyRoutingDataSource.setTargetDataSources(Collections.singletonMap("read1", readOnlyDataSource)); readOnlyRoutingDataSource.setDefaultTargetDataSource(defaultDataSource); readOnlyRoutingDataSource.afterPropertiesSet(); LazyConnectionDataSourceProxy dataSource = new LazyConnectionDataSourceProxy(readOnlyRoutingDataSource); DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); transactionDefinition.setReadOnly(true); TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource), transactionDefinition); //Act Connection connectionReturned = transactionTemplate.execute(status -> { try { return ((ConnectionProxy) dataSource.getConnection()).getTargetConnection(); } catch (SQLException e) { fail(e.getMessage()); } return null; }); //Assert assertSame(readOnlyConnection, connectionReturned); }
@Test public void getConnection_ReadReplicaAvailableWriteTransactionActive_returnsDefaultDataSource() throws Exception { //Arrange DataSource defaultDataSource = mock(DataSource.class); Connection connection = mock(Connection.class); DataSource readOnlyDataSource = mock(DataSource.class); Connection readOnlyConnection = mock(Connection.class); when(readOnlyDataSource.getConnection()).thenReturn(readOnlyConnection); when(defaultDataSource.getConnection()).thenReturn(connection); ReadOnlyRoutingDataSource readOnlyRoutingDataSource = new ReadOnlyRoutingDataSource(); readOnlyRoutingDataSource.setTargetDataSources(Collections.singletonMap("read1", readOnlyDataSource)); readOnlyRoutingDataSource.setDefaultTargetDataSource(defaultDataSource); readOnlyRoutingDataSource.afterPropertiesSet(); LazyConnectionDataSourceProxy dataSource = new LazyConnectionDataSourceProxy(readOnlyRoutingDataSource); DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); transactionDefinition.setReadOnly(false); TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource), transactionDefinition); //Act Connection connectionReturned = transactionTemplate.execute(status -> { try { return ((ConnectionProxy) dataSource.getConnection()).getTargetConnection(); } catch (SQLException e) { fail(e.getMessage()); } return null; }); //Assert assertSame(connection, connectionReturned); }
/** * Create a close-suppressing proxy for the given JDBC Connection. * Called by the {@code execute} method. * <p>The proxy also prepares returned JDBC Statements, applying * statement settings such as fetch size, max rows, and query timeout. * @param con the JDBC Connection to create a proxy for * @return the Connection proxy * @see java.sql.Connection#close() * @see #execute(ConnectionCallback) * @see #applyStatementSettings */ protected Connection createConnectionProxy(Connection con) { return (Connection) Proxy.newProxyInstance( ConnectionProxy.class.getClassLoader(), new Class<?>[] {ConnectionProxy.class}, new CloseSuppressingInvocationHandler(con)); }