1 16 package scriptella.jdbc; 17 18 import scriptella.configuration.ConfigurationException; 19 import scriptella.spi.AbstractConnection; 20 import scriptella.spi.ConnectionParameters; 21 import scriptella.spi.DialectIdentifier; 22 import scriptella.spi.ParametersCallback; 23 import scriptella.spi.QueryCallback; 24 import scriptella.spi.Resource; 25 import scriptella.util.StringUtils; 26 27 import java.sql.Connection ; 28 import java.sql.DatabaseMetaData ; 29 import java.sql.SQLException ; 30 import java.util.IdentityHashMap ; 31 import java.util.Map ; 32 import java.util.logging.Level ; 33 import java.util.logging.Logger ; 34 35 41 public class JdbcConnection extends AbstractConnection { 42 public static final String STATEMENT_CACHE_KEY = "statement.cache"; 43 public static final String STATEMENT_SEPARATOR_KEY = "statement.separator"; 44 public static final String STATEMENT_SEPARATOR_SINGLELINE_KEY = "statement.separator.singleline"; 45 public static final String KEEPFORMAT_KEY = "keepformat"; 46 public static final String TRANSACTION_ISOLATION_KEY = "transaction.isolation"; 47 public static final String TRANSACTION_ISOLATION_READ_UNCOMMITTED = "READ_UNCOMMITTED"; 48 public static final String TRANSACTION_ISOLATION_READ_COMMITTED = "READ_COMMITTED"; 49 public static final String TRANSACTION_ISOLATION_REPEATABLE_READ = "REPEATABLE_READ"; 50 public static final String TRANSACTION_ISOLATION_SERIALIZABLE = "SERIALIZABLE"; 51 private Connection con; 52 private static final Logger LOG = Logger.getLogger(JdbcConnection.class.getName()); 53 private boolean transactable; 54 private ParametersParser parametersParser; 55 int statementCacheSize; 56 protected String separator = ";"; 57 protected boolean separatorSingleLine; 58 protected boolean keepformat; 59 private Integer txIsolation; 60 private final Map <Resource, SqlExecutor> resourcesMap = new IdentityHashMap <Resource, SqlExecutor>(); 61 62 public JdbcConnection(Connection con, ConnectionParameters parameters) { 63 super(parameters); 64 if (con == null) { 65 throw new IllegalArgumentException ("Connection cannot be null"); 66 } 67 this.con = con; 68 init(parameters); 69 if (txIsolation != null) { 70 try { 71 con.setTransactionIsolation(txIsolation); 72 } catch (SQLException e) { 73 throw new JdbcException("Unable to set transaction isolation level for " + toString(), e); 74 } 75 } 76 77 try { 78 transactable = con.getTransactionIsolation() > Connection.TRANSACTION_NONE; 80 } catch (SQLException e) { 81 LOG.log(Level.WARNING, "Unable to determine transaction isolation level for connection " + toString(), e); 82 } 83 if (transactable) { try { 85 con.setAutoCommit(false); 86 } catch (Exception e) { 87 throw new JdbcException("Unable to set autocommit=false for " + toString(), e); 88 } 89 } 90 } 91 92 95 protected void init(ConnectionParameters parameters) { 96 97 statementCacheSize = parameters.getIntegerProperty(STATEMENT_CACHE_KEY, 64); 98 String separatorStr = parameters.getStringProperty(STATEMENT_SEPARATOR_KEY); 99 if (!StringUtils.isEmpty(separatorStr)) { 100 separator = separatorStr.trim(); 101 } 102 separatorSingleLine = parameters.getBooleanProperty(STATEMENT_SEPARATOR_SINGLELINE_KEY, false); 103 keepformat = parameters.getBooleanProperty(KEEPFORMAT_KEY, false); 104 String isolationStr = parameters.getStringProperty(TRANSACTION_ISOLATION_KEY); 105 if (isolationStr != null) { 106 isolationStr = isolationStr.trim(); 107 if (TRANSACTION_ISOLATION_READ_COMMITTED.equalsIgnoreCase(isolationStr)) { 108 txIsolation = Connection.TRANSACTION_READ_COMMITTED; 109 } else if (TRANSACTION_ISOLATION_READ_UNCOMMITTED.equalsIgnoreCase(isolationStr)) { 110 txIsolation = Connection.TRANSACTION_READ_UNCOMMITTED; 111 } else if (TRANSACTION_ISOLATION_REPEATABLE_READ.equalsIgnoreCase(isolationStr)) { 112 txIsolation = Connection.TRANSACTION_REPEATABLE_READ; 113 } else if (TRANSACTION_ISOLATION_SERIALIZABLE.equalsIgnoreCase(isolationStr)) { 114 txIsolation = Connection.TRANSACTION_SERIALIZABLE; 115 } else if (StringUtils.isDecimalInt(isolationStr)) { 116 txIsolation = parameters.getIntegerProperty(TRANSACTION_ISOLATION_KEY); 117 } else { 118 throw new ConfigurationException( 119 "Invalid " + TRANSACTION_ISOLATION_KEY + " connection property value: " + isolationStr + 120 ". Valid values are: " + TRANSACTION_ISOLATION_READ_COMMITTED + ", " + 121 TRANSACTION_ISOLATION_READ_UNCOMMITTED + ", " + TRANSACTION_ISOLATION_REPEATABLE_READ + 122 ", " + TRANSACTION_ISOLATION_SERIALIZABLE + 123 " or a numeric value according to java.sql.Connection transaction isolation constants"); 124 } 125 126 } 127 parametersParser = new ParametersParser(parameters.getContext()); 128 initDialectIdentifier(); 129 } 130 131 StatementCounter getStatementCounter() { 132 return counter; 133 } 134 135 141 protected void initDialectIdentifier() { 142 try { 143 final DatabaseMetaData metaData = con.getMetaData(); 144 if (metaData != null) { setDialectIdentifier(new DialectIdentifier(metaData.getDatabaseProductName(), 146 metaData.getDatabaseProductVersion())); 147 } 148 } catch (Exception e) { 149 setDialectIdentifier(DialectIdentifier.NULL_DIALECT); 150 LOG.log(Level.WARNING, "Failed to obtain meta data for connection. No dialect checking for " + con, e); 151 } 152 } 153 154 public void executeScript(Resource scriptContent, ParametersCallback parametersCallback) { 155 SqlExecutor s = resourcesMap.get(scriptContent); 156 if (s == null) { 157 resourcesMap.put(scriptContent, s = new SqlExecutor(scriptContent, this)); 158 } 159 s.execute(parametersCallback); 160 } 161 162 public void executeQuery(Resource queryContent, ParametersCallback parametersCallback, QueryCallback queryCallback) { 163 SqlExecutor q = resourcesMap.get(queryContent); 164 if (q == null) { 165 resourcesMap.put(queryContent, q = new SqlExecutor(queryContent, this)); 166 } 167 q.execute(parametersCallback, queryCallback); 168 if (q.getUpdateCount() < 0) { 169 throw new JdbcException("SQL query cannot make updates"); 170 } 171 } 172 173 ParametersParser getParametersParser() { 174 return parametersParser; 175 } 176 177 public void commit() { 178 if (con == null) { 179 throw new IllegalStateException ("Attempt to commit a transaction on a closed connection"); 180 } 181 if (!transactable) { 182 LOG.log(Level.INFO, "Connection " + toString() + " doesn't support transactions. Commit ignored."); 183 } else { 184 try { 185 con.commit(); 186 } catch (Exception e) { 187 throw new JdbcException("Unable to commit transaction", e); 188 } 189 } 190 } 191 192 public void rollback() { 193 if (con == null) { 194 throw new IllegalStateException ("Attempt to roll back a transaction on a closed connection"); 195 } 196 if (!transactable) { 197 LOG.log(Level.INFO, "Connection " + toString() + " doesn't support transactions. Rollback ignored."); 198 } else { 199 try { 200 con.rollback(); 201 } catch (Exception e) { 202 throw new JdbcException("Unable to roll back transaction", e); 203 } 204 } 205 } 206 207 public void close() { 208 if (con != null) { 209 for (SqlExecutor element : resourcesMap.values()) { 211 element.close(); 212 } 213 resourcesMap.clear(); 214 try { 215 con.close(); 216 con = null; 217 } catch (SQLException e) { 218 throw new JdbcException("Unable to close a connection", e); 219 } 220 221 } 222 } 223 224 public Connection getNativeConnection() { 225 return con; 226 } 227 228 public String toString() { 229 return "JdbcConnection{" + (con == null ? "" : con.getClass().getName()) + '}'; 230 } 231 232 } 233 | Popular Tags |