1 package org.hibernate.jdbc; 3 4 import org.hibernate.ConnectionReleaseMode; 5 import org.hibernate.HibernateException; 6 import org.hibernate.engine.SessionFactoryImplementor; 7 import org.hibernate.exception.JDBCExceptionHelper; 8 import org.hibernate.util.JDBCExceptionReporter; 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 12 import java.sql.Connection ; 13 import java.sql.SQLException ; 14 import java.io.Serializable ; 15 import java.io.ObjectInputStream ; 16 import java.io.IOException ; 17 import java.io.ObjectOutputStream ; 18 19 27 public class ConnectionManager implements Serializable { 28 29 33 private static final Log log = LogFactory.getLog( ConnectionManager.class ); 34 35 public static interface Callback { 36 public void connectionOpened(); 37 public void connectionCleanedUp(); 38 } 39 40 private transient SessionFactoryImplementor factory; 41 private final Callback callback; 42 43 private final ConnectionReleaseMode releaseMode; 44 private transient Connection connection; 45 46 private final boolean wasConnectionSupplied; 47 private transient boolean shouldObtainConnection; 48 private transient Batcher batcher; 49 50 60 public ConnectionManager( 61 SessionFactoryImplementor factory, 62 Callback callback, 63 ConnectionReleaseMode releaseMode, 64 Connection connection) { 65 this.factory = factory; 66 this.callback = callback; 67 68 this.batcher = factory.getSettings().getBatcherFactory().createBatcher( this ); 69 70 this.releaseMode = releaseMode; 71 72 this.connection = connection; 73 wasConnectionSupplied = ( connection != null ); 74 shouldObtainConnection = !wasConnectionSupplied; 75 } 76 77 82 public SessionFactoryImplementor getFactory() { 83 return factory; 84 } 85 86 91 public Batcher getBatcher() { 92 return batcher; 93 } 94 95 107 public Connection getConnection() throws HibernateException { 108 if ( connection == null ) { 109 if ( shouldObtainConnection ) { 110 openConnection(); 111 } 112 else { 113 throw new HibernateException( "Not able to obtain connection" ); 114 } 115 } 116 return connection; 117 } 118 119 127 public boolean isAutoCommit() throws SQLException { 128 return connection == null || connection.getAutoCommit(); 129 } 130 131 138 public boolean isLogicallyConnected() { 139 return connection != null || shouldObtainConnection; 140 } 141 142 148 public boolean isPhysicallyConnected() { 149 return connection != null; 150 } 151 152 157 public void afterStatement() { 158 if ( releaseMode == ConnectionReleaseMode.AFTER_STATEMENT ) { 159 if ( batcher.hasOpenResources() ) { 160 log.info( "Skipping aggresive-release due to open resources on batcher" ); 161 } 162 else { 163 aggressiveRelease(); 164 } 165 } 166 } 167 168 173 public void afterTransaction() { 174 if ( releaseMode == ConnectionReleaseMode.AFTER_TRANSACTION ) { 175 aggressiveRelease(); 178 } 179 } 180 181 188 public Connection close() { 189 if ( connection==null ) { 190 shouldObtainConnection = false; 191 return null; 192 } 193 else { 194 return cleanup(); 195 } 196 } 197 198 205 public Connection manualDisconnect() { 206 return cleanup(); 207 } 208 209 215 public void manualReconnect() { 216 if ( isLogicallyConnected() ) { 217 throw new HibernateException( "Already connected" ); 218 } 219 220 shouldObtainConnection = true; 221 } 222 223 229 public void manualReconnect(Connection suppliedConnection) { 230 if ( isLogicallyConnected() ) { 231 throw new HibernateException( "Already connected" ); 232 } 233 234 this.connection = suppliedConnection; 235 } 236 237 247 private Connection cleanup() throws HibernateException { 248 try { 249 if ( shouldObtainConnection ) { 250 shouldObtainConnection = false; 252 return null; 253 } 254 else { 255 if (connection==null) { 256 throw new HibernateException( "Already disconnected" ); 257 } 258 259 batcher.closeStatements(); 260 Connection c = null; 261 if ( !wasConnectionSupplied ) { 262 closeConnection(); 263 } 264 else { 265 c = connection; 266 } 267 connection = null; 268 return c; 269 } 270 } 271 finally { 272 callback.connectionCleanedUp(); 273 } 274 } 275 276 280 private void aggressiveRelease() { 281 if ( !wasConnectionSupplied ) { 282 log.debug( "aggressively releasing JDBC connection" ); 283 if ( connection != null ) { 284 closeConnection(); 285 } 286 shouldObtainConnection = true; 287 } 288 } 289 290 295 private void openConnection() throws HibernateException { 296 log.debug("opening JDBC connection"); 297 try { 298 connection = factory.getConnectionProvider().getConnection(); 299 } 300 catch (SQLException sqle) { 301 throw JDBCExceptionHelper.convert( 302 factory.getSQLExceptionConverter(), 303 sqle, 304 "Cannot open connection" 305 ); 306 } 307 308 shouldObtainConnection = false; 309 callback.connectionOpened(); } 311 312 315 private void closeConnection() { 316 if ( log.isDebugEnabled() ) { 317 log.debug( 318 "closing JDBC connection [" + 319 batcher.openResourceStatsAsString() + "]" 320 ); 321 } 322 323 try { 324 if ( !connection.isClosed() ) { 325 JDBCExceptionReporter.logAndClearWarnings( connection ); 326 } 327 factory.getConnectionProvider().closeConnection( connection ); 328 connection = null; 329 } 330 catch (SQLException sqle) { 331 throw JDBCExceptionHelper.convert( 332 factory.getSQLExceptionConverter(), 333 sqle, 334 "Cannot close connection" 335 ); 336 } 337 } 338 339 345 private void writeObject(ObjectOutputStream oos) throws IOException { 346 if ( isPhysicallyConnected() ) { 347 throw new IllegalStateException ( "Cannot serialize a ConnectionManager while connected" ); 348 } 349 350 oos.writeObject( factory ); 351 oos.defaultWriteObject(); 352 } 353 354 361 private void readObject(ObjectInputStream ois) throws IOException , ClassNotFoundException { 362 factory = ( SessionFactoryImplementor ) ois.readObject(); 363 ois.defaultReadObject(); 364 365 this.batcher = factory.getSettings().getBatcherFactory().createBatcher( this ); 366 } 367 368 371 protected void finalize() throws Throwable { 372 373 log.debug( "running Session.finalize()" ); 374 375 if ( connection != null ) { 376 if ( connection.isClosed() ) { 377 log.warn( "finalizing with closed connection" ); 378 } 379 else { 380 log.warn("unclosed connection, forgot to call close() on your session?"); 381 if ( !wasConnectionSupplied ) { 383 connection.close(); 384 } 385 } 386 } 387 } 388 } 389 | Popular Tags |