1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.dbcp2;
19
20 import static org.junit.jupiter.api.Assertions.assertFalse;
21 import static org.junit.jupiter.api.Assertions.assertNotSame;
22 import static org.junit.jupiter.api.Assertions.assertSame;
23 import static org.junit.jupiter.api.Assertions.assertThrows;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25
26 import java.sql.Connection;
27 import java.sql.DriverManager;
28 import java.sql.PreparedStatement;
29 import java.sql.SQLException;
30 import java.sql.Statement;
31
32 import javax.management.ObjectName;
33 import javax.sql.DataSource;
34
35 import org.apache.commons.pool2.ObjectPool;
36 import org.apache.commons.pool2.impl.GenericObjectPool;
37 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
38 import org.junit.jupiter.api.Assertions;
39 import org.junit.jupiter.api.Test;
40
41
42
43
44 public class TestPStmtPooling {
45
46 private DataSource createPoolingDataSource() throws Exception {
47 DriverManager.registerDriver(new TesterDriver());
48 final ConnectionFactory connFactory = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "u1", "p1");
49
50 final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, null);
51 pcf.setPoolStatements(true);
52 pcf.setDefaultReadOnly(Boolean.FALSE);
53 pcf.setDefaultAutoCommit(Boolean.TRUE);
54 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
55 pcf.setPool(connPool);
56
57 return new PoolingDataSource<>(connPool);
58
59 }
60
61 private PoolablePreparedStatement<?> getPoolablePreparedStatement(Statement s) {
62
63 while (s != null) {
64 if (s instanceof PoolablePreparedStatement) {
65 return (PoolablePreparedStatement<?>) s;
66 }
67 if (!(s instanceof DelegatingPreparedStatement)) {
68 return null;
69 }
70 s = ((DelegatingPreparedStatement) s).getDelegate();
71 }
72 return null;
73 }
74
75 @Test
76 void testBatchUpdate() throws Exception {
77 DriverManager.registerDriver(new TesterDriver());
78 final ConnectionFactory connFactory = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "u1", "p1");
79
80 final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, null);
81 pcf.setPoolStatements(true);
82 pcf.setDefaultReadOnly(Boolean.FALSE);
83 pcf.setDefaultAutoCommit(Boolean.TRUE);
84 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
85 pcf.setPool(connPool);
86
87 final PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
88
89 final Connection conn = ds.getConnection();
90 final PreparedStatement ps = conn.prepareStatement("select 1 from dual");
91 final Statement inner = ((DelegatingPreparedStatement) ps).getInnermostDelegate();
92
93 ps.addBatch();
94 ps.close();
95 conn.close();
96 Assertions.assertFalse(inner.isClosed());
97 ds.close();
98 }
99
100 @Test
101 void testCallableStatementPooling() throws Exception {
102 DriverManager.registerDriver(new TesterDriver());
103 final ConnectionFactory connFactory = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "u1", "p1");
104
105 final ObjectName oName = new ObjectName("UnitTests:DataSource=test");
106 final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, oName);
107 pcf.setPoolStatements(true);
108 pcf.setDefaultReadOnly(Boolean.FALSE);
109 pcf.setDefaultAutoCommit(Boolean.TRUE);
110
111 final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
112 config.setJmxNameBase("UnitTests:DataSource=test,connectionpool=connections");
113 config.setJmxNamePrefix("");
114 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf, config);
115 pcf.setPool(connPool);
116
117 final PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
118
119 try (Connection conn = ds.getConnection()) {
120 final Statement stmt1 = conn.prepareStatement("select 1 from dual");
121 final Statement ustmt1 = ((DelegatingStatement) stmt1).getInnermostDelegate();
122 final Statement cstmt1 = conn.prepareCall("{call home}");
123 final Statement ucstmt1 = ((DelegatingStatement) cstmt1).getInnermostDelegate();
124 stmt1.close();
125 cstmt1.close();
126 final Statement stmt2 = conn.prepareStatement("select 1 from dual");
127 final Statement ustmt2 = ((DelegatingStatement) stmt2).getInnermostDelegate();
128 final Statement cstmt2 = conn.prepareCall("{call home}");
129 final Statement ucstmt2 = ((DelegatingStatement) cstmt2).getInnermostDelegate();
130 stmt2.close();
131 cstmt2.close();
132 assertSame(ustmt1, ustmt2);
133 assertSame(ucstmt1, ucstmt2);
134
135 final Statement stmt3 = conn.prepareCall("select 1 from dual");
136 final Statement ustmt3 = ((DelegatingStatement) stmt3).getInnermostDelegate();
137 stmt3.close();
138 assertNotSame(ustmt1, ustmt3);
139 assertNotSame(ustmt3, ucstmt1);
140 }
141 ds.close();
142 }
143
144 @Test
145 void testClosePool() throws Exception {
146 DriverManager.registerDriver(new TesterDriver());
147 final ConnectionFactory connFactory = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "u1", "p1");
148
149 final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, null);
150 pcf.setPoolStatements(true);
151 pcf.setDefaultReadOnly(Boolean.FALSE);
152 pcf.setDefaultAutoCommit(Boolean.TRUE);
153
154 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
155 pcf.setPool(connPool);
156
157 final PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
158 ((PoolingDataSource<?>) ds).setAccessToUnderlyingConnectionAllowed(true);
159
160 final Connection conn = ds.getConnection();
161 try (Statement s = conn.prepareStatement("select 1 from dual")) {
162 }
163
164 final Connection poolableConnection = ((DelegatingConnection<?>) conn).getDelegate();
165 final Connection poolingConnection = ((DelegatingConnection<?>) poolableConnection).getDelegate();
166 poolingConnection.close();
167 final SQLException ex = assertThrows(SQLException.class, () -> conn.prepareStatement("select 1 from dual"));
168 assertTrue(ex.getMessage().endsWith("invalid PoolingConnection."));
169 ds.close();
170 }
171
172
173
174
175
176 @Test
177 void testMultipleClose() throws Exception {
178 final DataSource ds = createPoolingDataSource();
179 final Connection conn = ds.getConnection();
180 final PreparedStatement stmt1 = conn.prepareStatement("select 1 from dual");
181 final PoolablePreparedStatement<?> pps1 = getPoolablePreparedStatement(stmt1);
182 conn.close();
183 assertTrue(stmt1.isClosed());
184 stmt1.close();
185 assertTrue(stmt1.isClosed());
186 final Connection conn2 = ds.getConnection();
187 final PreparedStatement stmt2 = conn2.prepareStatement("select 1 from dual");
188
189 Assertions.assertSame(pps1, getPoolablePreparedStatement(stmt2));
190 stmt1.close();
191 assertFalse(stmt2.isClosed());
192 stmt2.executeQuery();
193 conn2.close();
194 assertTrue(stmt1.isClosed());
195 assertTrue(stmt2.isClosed());
196 }
197
198 @Test
199 void testStmtPool() throws Exception {
200 final DataSource ds = createPoolingDataSource();
201 try (Connection conn = ds.getConnection()) {
202 final Statement stmt1 = conn.prepareStatement("select 1 from dual");
203 final Statement ustmt1 = ((DelegatingStatement) stmt1).getInnermostDelegate();
204 stmt1.close();
205 final Statement stmt2 = conn.prepareStatement("select 1 from dual");
206 final Statement ustmt2 = ((DelegatingStatement) stmt2).getInnermostDelegate();
207 stmt2.close();
208 assertSame(ustmt1, ustmt2);
209 }
210 }
211 }