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.assertTrue;
24 import static org.junit.jupiter.api.Assertions.fail;
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(
49 "jdbc:apache:commons:testdriver","u1","p1");
50
51 final PoolableConnectionFactory pcf =
52 new PoolableConnectionFactory(connFactory, null);
53 pcf.setPoolStatements(true);
54 pcf.setDefaultReadOnly(Boolean.FALSE);
55 pcf.setDefaultAutoCommit(Boolean.TRUE);
56 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
57 pcf.setPool(connPool);
58
59 return new PoolingDataSource<>(connPool);
60
61 }
62
63 private PoolablePreparedStatement<?> getPoolablePreparedStatement(Statement s) {
64
65 while (s != null) {
66 if (s instanceof PoolablePreparedStatement) {
67 return (PoolablePreparedStatement<?>) s;
68 }
69 if (!(s instanceof DelegatingPreparedStatement)) {
70 return null;
71 }
72 s = ((DelegatingPreparedStatement) s).getDelegate();
73 }
74 return null;
75 }
76
77 @Test
78 public void testBatchUpdate() throws Exception {
79 DriverManager.registerDriver(new TesterDriver());
80 final ConnectionFactory connFactory = new DriverManagerConnectionFactory(
81 "jdbc:apache:commons:testdriver","u1","p1");
82
83 final PoolableConnectionFactory pcf =
84 new PoolableConnectionFactory(connFactory, null);
85 pcf.setPoolStatements(true);
86 pcf.setDefaultReadOnly(Boolean.FALSE);
87 pcf.setDefaultAutoCommit(Boolean.TRUE);
88 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
89 pcf.setPool(connPool);
90
91 final PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
92
93 final Connection conn = ds.getConnection();
94 final PreparedStatement ps = conn.prepareStatement("select 1 from dual");
95 final Statement inner = ((DelegatingPreparedStatement) ps).getInnermostDelegate();
96
97 ps.addBatch();
98 ps.close();
99 conn.close();
100 Assertions.assertFalse(inner.isClosed());
101 ds.close();
102 }
103
104 @Test
105 public void testCallableStatementPooling() throws Exception {
106 DriverManager.registerDriver(new TesterDriver());
107 final ConnectionFactory connFactory = new DriverManagerConnectionFactory(
108 "jdbc:apache:commons:testdriver","u1","p1");
109
110 final ObjectName oName = new ObjectName("UnitTests:DataSource=test");
111 final PoolableConnectionFactory pcf =
112 new PoolableConnectionFactory(connFactory, oName);
113 pcf.setPoolStatements(true);
114 pcf.setDefaultReadOnly(Boolean.FALSE);
115 pcf.setDefaultAutoCommit(Boolean.TRUE);
116
117 final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
118 config.setJmxNameBase("UnitTests:DataSource=test,connectionpool=connections");
119 config.setJmxNamePrefix("");
120 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf, config);
121 pcf.setPool(connPool);
122
123 final PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
124
125 try (Connection conn = ds.getConnection()) {
126 final Statement stmt1 = conn.prepareStatement("select 1 from dual");
127 final Statement ustmt1 = ((DelegatingStatement) stmt1).getInnermostDelegate();
128 final Statement cstmt1 = conn.prepareCall("{call home}");
129 final Statement ucstmt1 = ((DelegatingStatement) cstmt1).getInnermostDelegate();
130 stmt1.close();
131 cstmt1.close();
132 final Statement stmt2 = conn.prepareStatement("select 1 from dual");
133 final Statement ustmt2 = ((DelegatingStatement) stmt2).getInnermostDelegate();
134 final Statement cstmt2 = conn.prepareCall("{call home}");
135 final Statement ucstmt2 = ((DelegatingStatement) cstmt2).getInnermostDelegate();
136 stmt2.close();
137 cstmt2.close();
138 assertSame(ustmt1, ustmt2);
139 assertSame(ucstmt1, ucstmt2);
140
141 final Statement stmt3 = conn.prepareCall("select 1 from dual");
142 final Statement ustmt3 = ((DelegatingStatement) stmt3).getInnermostDelegate();
143 stmt3.close();
144 assertNotSame(ustmt1, ustmt3);
145 assertNotSame(ustmt3, ucstmt1);
146 }
147 ds.close();
148 }
149
150 @Test
151 public void testClosePool() throws Exception {
152 DriverManager.registerDriver(new TesterDriver());
153 final ConnectionFactory connFactory = new DriverManagerConnectionFactory(
154 "jdbc:apache:commons:testdriver","u1","p1");
155
156 final PoolableConnectionFactory pcf =
157 new PoolableConnectionFactory(connFactory, null);
158 pcf.setPoolStatements(true);
159 pcf.setDefaultReadOnly(Boolean.FALSE);
160 pcf.setDefaultAutoCommit(Boolean.TRUE);
161
162 final ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
163 pcf.setPool(connPool);
164
165 final PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
166 ((PoolingDataSource<?>) ds).setAccessToUnderlyingConnectionAllowed(true);
167
168 final Connection conn = ds.getConnection();
169 try (Statement s = conn.prepareStatement("select 1 from dual")) {}
170
171 final Connection poolableConnection = ((DelegatingConnection<?>) conn).getDelegate();
172 final Connection poolingConnection =
173 ((DelegatingConnection<?>) poolableConnection).getDelegate();
174 poolingConnection.close();
175 try (PreparedStatement ps = conn.prepareStatement("select 1 from dual")) {
176 fail("Expecting SQLException");
177 } catch (final SQLException ex) {
178 assertTrue(ex.getMessage().endsWith("invalid PoolingConnection."));
179 }
180 ds.close();
181 }
182
183
184
185
186
187
188 @Test
189 public void testMultipleClose() throws Exception {
190 final DataSource ds = createPoolingDataSource();
191 final Connection conn = ds.getConnection();
192 final PreparedStatement stmt1 = conn.prepareStatement("select 1 from dual");
193 final PoolablePreparedStatement<?> pps1 = getPoolablePreparedStatement(stmt1);
194 conn.close();
195 assertTrue(stmt1.isClosed());
196 stmt1.close();
197 assertTrue(stmt1.isClosed());
198 final Connection conn2 = ds.getConnection();
199 final PreparedStatement stmt2 = conn2.prepareStatement("select 1 from dual");
200
201 Assertions.assertSame(pps1, getPoolablePreparedStatement(stmt2));
202 stmt1.close();
203 assertFalse(stmt2.isClosed());
204 stmt2.executeQuery();
205 conn2.close();
206 assertTrue(stmt1.isClosed());
207 assertTrue(stmt2.isClosed());
208 }
209
210 @Test
211 public void testStmtPool() throws Exception {
212 final DataSource ds = createPoolingDataSource();
213 try (Connection conn = ds.getConnection()) {
214 final Statement stmt1 = conn.prepareStatement("select 1 from dual");
215 final Statement ustmt1 = ((DelegatingStatement) stmt1).getInnermostDelegate();
216 stmt1.close();
217 final Statement stmt2 = conn.prepareStatement("select 1 from dual");
218 final Statement ustmt2 = ((DelegatingStatement) stmt2).getInnermostDelegate();
219 stmt2.close();
220 assertSame(ustmt1, ustmt2);
221 }
222 }
223 }