1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.driver.jdbc.core.statement;
19
20 import lombok.EqualsAndHashCode;
21 import lombok.RequiredArgsConstructor;
22 import org.apache.shardingsphere.driver.jdbc.adapter.executor.ForceExecuteTemplate;
23 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
24 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
25 import org.apache.shardingsphere.infra.executor.sql.execute.engine.ConnectionMode;
26 import org.apache.shardingsphere.infra.executor.sql.prepare.driver.jdbc.ExecutorJDBCStatementManager;
27 import org.apache.shardingsphere.infra.executor.sql.prepare.driver.jdbc.StatementOption;
28
29 import java.sql.Connection;
30 import java.sql.PreparedStatement;
31 import java.sql.SQLException;
32 import java.sql.SQLFeatureNotSupportedException;
33 import java.sql.Statement;
34 import java.util.Map;
35 import java.util.concurrent.ConcurrentHashMap;
36
37
38
39
40 public final class StatementManager implements ExecutorJDBCStatementManager, AutoCloseable {
41
42 private final Map<CacheKey, Statement> cachedStatements = new ConcurrentHashMap<>();
43
44 private final ForceExecuteTemplate<Statement> forceExecuteTemplate = new ForceExecuteTemplate<>();
45
46 @Override
47 public Statement createStorageResource(final Connection connection, final ConnectionMode connectionMode, final StatementOption option, final DatabaseType databaseType) throws SQLException {
48 return createStatement(connection, option);
49 }
50
51 @Override
52 public Statement createStorageResource(final ExecutionUnit executionUnit, final Connection connection, final ConnectionMode connectionMode, final StatementOption option,
53 final DatabaseType databaseType) throws SQLException {
54 Statement result = cachedStatements.get(new CacheKey(executionUnit, connectionMode));
55 if (null == result || result.isClosed() || result.getConnection().isClosed()) {
56 String sql = executionUnit.getSqlUnit().getSql();
57 if (option.isReturnGeneratedKeys()) {
58 result = null == option.getColumns() || 0 == option.getColumns().length
59 ? connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
60 : connection.prepareStatement(sql, option.getColumns());
61 } else {
62 result = prepareStatement(connection, option, sql);
63 }
64 cachedStatements.put(new CacheKey(executionUnit, connectionMode), result);
65 }
66 return result;
67 }
68
69 @SuppressWarnings("MagicConstant")
70 private Statement createStatement(final Connection connection, final StatementOption option) throws SQLException {
71 Statement result;
72 try {
73 result = connection.createStatement(option.getResultSetType(), option.getResultSetConcurrency(), option.getResultSetHoldability());
74 } catch (final SQLFeatureNotSupportedException ignore) {
75 result = connection.createStatement();
76 }
77 return result;
78 }
79
80 @SuppressWarnings("MagicConstant")
81 private PreparedStatement prepareStatement(final Connection connection, final StatementOption option, final String sql) throws SQLException {
82 PreparedStatement result;
83 try {
84 result = connection.prepareStatement(sql, option.getResultSetType(), option.getResultSetConcurrency(), option.getResultSetHoldability());
85 } catch (final SQLFeatureNotSupportedException ignore) {
86 result = connection.prepareStatement(sql);
87 }
88 return result;
89 }
90
91 @Override
92 public void close() throws SQLException {
93 try {
94 forceExecuteTemplate.execute(cachedStatements.values(), Statement::close);
95 } finally {
96 cachedStatements.clear();
97 }
98 }
99
100 @RequiredArgsConstructor
101 @EqualsAndHashCode
102 private static final class CacheKey {
103
104 private final ExecutionUnit executionUnit;
105
106 private final ConnectionMode connectionMode;
107 }
108 }