/*
 * Copyright 2002-2006 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.orm.jpa.vendor;

import java.sql.Connection;
import java.sql.SQLException;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;

import org.hibernate.Session;
import org.hibernate.ejb.HibernateEntityManager;

import org.springframework.jdbc.datasource.ConnectionHandle;
import org.springframework.jdbc.datasource.SimpleConnectionHandle;
import org.springframework.orm.jpa.DefaultJpaDialect;

/**
 * {@link org.springframework.orm.jpa.JpaDialect} implementation for
 * Hibernate EntityManager. Developed and tested against Hibernate 3.2.
 *
 * @author Costin Leau
 * @author Juergen Hoeller
 * @since 2.0
 */
public class HibernateJpaDialect extends DefaultJpaDialect {

	@Override
	public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly)
			throws PersistenceException, SQLException {

		Session session = getSession(entityManager);
		Connection con = session.connection();
		return (con != null ? new SimpleConnectionHandle(con) : null);
	}

	protected Session getSession(EntityManager em) {
		return ((HibernateEntityManager) em).getSession();
	}

}

@@ -803,24 +803,56 @@
 Exception;%0A%0A
+import org.hibernate.FlushMode;%0A
 import org.h
@@ -1100,16 +1100,139 @@
 Dialect;
+%0Aimport org.springframework.transaction.TransactionDefinition;%0Aimport org.springframework.transaction.TransactionException;
 %0A%0A/**%0A *
@@ -1508,415 +1508,1771 @@
 %7B%0A%0A%09
-@Override%0A%09public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly)%0A%09%09%09throws PersistenceException, SQLException %7B%0A%0A%09%09Session session = getSession(entityManager);%0A%09%09Connection con = session.connection();%0A%09%09return (con != null ? new SimpleConnectionHandle(con) : null);%0A%09%7D%0A%0A%09protected Session getSession(EntityManager em) %7B%0A%09%09return ((HibernateEntityManager) em).getSession();
+public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition)%0A%09%09%09throws PersistenceException, SQLException, TransactionException %7B%0A%0A%09%09super.beginTransaction(entityManager, definition);%0A%09%09Session session = getSession(entityManager);%0A%09%09FlushMode flushMode = session.getFlushMode();%0A%09%09FlushMode previousFlushMode = null;%0A%09%09if (definition.isReadOnly()) %7B%0A%09%09%09// We should suppress flushing for a read-only transaction.%0A%09%09%09session.setFlushMode(FlushMode.MANUAL);%0A%09%09%09previousFlushMode = flushMode;%0A%09%09%7D%0A%09%09else %7B%0A%09%09%09// We need AUTO or COMMIT for a non-read-only transaction.%0A%09%09%09if (flushMode.lessThan(FlushMode.COMMIT)) %7B%0A%09%09%09%09session.setFlushMode(FlushMode.AUTO);%0A%09%09%09%09previousFlushMode = flushMode;%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return new SessionTransactionData(session, previousFlushMode);%0A%09%7D%0A%0A%09public void cleanupTransaction(Object transactionData) %7B%0A%09%09((SessionTransactionData) transactionData).resetFlushMode();%0A%09%7D%0A%0A%09@Override%0A%09public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly)%0A%09%09%09throws PersistenceException, SQLException %7B%0A%0A%09%09Session session = getSession(entityManager);%0A%09%09Connection con = session.connection();%0A%09%09return (con != null ? new SimpleConnectionHandle(con) : null);%0A%09%7D%0A%0A%09protected Session getSession(EntityManager em) %7B%0A%09%09return ((HibernateEntityManager) em).getSession();%0A%09%7D%0A%0A%0A%09private static class SessionTransactionData %7B%0A%0A%09%09private final Session session;%0A%0A%09%09private final FlushMode previousFlushMode;%0A%0A%09%09public SessionTransactionData(Session session, FlushMode previousFlushMode) %7B%0A%09%09%09this.session = session;%0A%09%09%09this.previousFlushMode = previousFlushMode;%0A%09%09%7D%0A%0A%09%09public void resetFlushMode() %7B%0A%09%09%09if (this.previousFlushMode != null) %7B%0A%09%09%09%09this.session.setFlushMode(this.previousFlushMode);%0A%09%09%09%7D%0A%09%09%7D
 %0A%09%7D%0A

switch FlushMode to MANUAL in case of read-only, and enforce COMMIT or AUTO for read-write transaction