1. 程式人生 > >hibernate Session與dataSource連線的關係

hibernate Session與dataSource連線的關係

  1. 一個事務同一時刻只能佔有一個數據庫連結
  2. 一個數據庫連結可以被多個事務使用,取決於資料庫的連線池
  3. 資料庫連線池中空閒連結超時,回收。
  4. 一個事務執行時間超過了資料庫連線池的最大
protected void doBegin(Object transaction, TransactionDefinition definition) {
		HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
		......

		Session session = null;
		try {
		  // 判斷當前事務有無Session或者需不需以事務的方式執行
			if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
				Interceptor entityInterceptor = getEntityInterceptor();
				// 獲取新的事務
				Session newSession = (entityInterceptor != null ?
						getSessionFactory().withOptions().interceptor(entityInterceptor).openSession() :
						getSessionFactory().openSession());
				if (logger.isDebugEnabled()) {
					logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
				}
				txObject.setSession(newSession);
			}

			session = txObject.getSessionHolder().getSession();

             // 是否提前準備資料庫連結並且是否Session一直持有同一個connection
			if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
				// We're allowed to change the transaction settings of the JDBC Connection.
				if (logger.isDebugEnabled()) {
					logger.debug("Preparing JDBC Connection of Hibernate Session [" + session + "]");
				}
				// 獲取一個connection,並與當前Session繫結
				Connection con = ((SessionImplementor) session).connection();
				Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
				txObject.setPreviousIsolationLevel(previousIsolationLevel);
				if (this.allowResultAccessAfterCompletion && !txObject.isNewSession()) {
					int currentHoldability = con.getHoldability();
					if (currentHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
						txObject.setPreviousHoldability(currentHoldability);
						con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
					}
				}
			}
			.......
			// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
			if (getDataSource() != null) {
				Connection con = ((SessionImplementor) session).connection();
				ConnectionHolder conHolder = new ConnectionHolder(con);
				if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
					conHolder.setTimeoutInSeconds(timeout);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
				}
				TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
				txObject.setConnectionHolder(conHolder);
			}
		}
	}

在一個事務開始前,對Session以及相關的connection進行了初始化。其中 Connection con = ((SessionImplementor) session).connection();是通過呼叫SessionImpl的connection方法完成的繫結資料庫連結。

	@Override
	public Connection connection() throws HibernateException {
		errorIfClosed();
		return this.jdbcCoordinator.getLogicalConnection().getPhysicalConnection();
	}

獲得一個具體的真實的物理資料庫連結是通過具體的資料庫連結提供類完成的。以常見的mysql jdbc為例:

	@Override
	public Connection getConnection() throws SQLException {
		if ( !available ) {
			throw new HibernateException( "Provider is closed!" );
		}
		return useCredentials ? dataSource.getConnection( user, pass ) : dataSource.getConnection();
	}