2010-11-11 11 views
9

Tengo un método, marcado como @Transactional. Consta de varias funciones, una de ellas utiliza JDBC y la segunda, Hibernate, tercera, JDBC. El problema es que los cambios realizados por la función Hibernate no son visibles en las últimas funciones, que funcionan con JDBC.Hibernate y JDBC en una transacción

@Transactional 
void update() { 
    jdbcUpdate1(); 
    hibernateupdate1(); 
    jdbcUpdate2(); // results of hibernateupdate1() are not visible here  
} 

Todas las funciones están configurados para utilizar la misma fuente de datos:

<bean id="myDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> 
     <property name="targetDataSource" ref="targetDataSource"/> 
    </bean> 

    <bean id="targetDataSource" class="org.apache.commons.dbcp.BasicDataSource" 
      destroy-method="close" lazy-init="true" scope="singleton"> 
     <!-- settings here --> 
    </bean> 

frijol myDataSource se utiliza en el código. myDataSource.getConnection() se utiliza para trabajar con conexiones en funciones JDBC y

getHibernateTemplate().execute(new HibernateCallback() { 
      public Object doInHibernate(Session session) throws HibernateException, SQLException { 
       ... 
      } 
     }); 

se utiliza en función de hibernación. Gracias.

Respuesta

10

Primero, evite usar JDBC cuando use hibernate.

Luego, si realmente lo necesita, use Session.doWork(..). Si su versión de hibernación aún no tiene este método, obtenga Connection en session.connection().

+2

Para aquellos que llegarán desde Google, mi solución para este problema. Añadí session.flush() al final de la función de limpieza de hibernación. Después de esto, su resultado de escritura está disponible en la siguiente función de lectura jdbc (en la misma transacción). – alex543

2

Puede usar JDBC y Hibernate en la misma transacción si se utiliza la configuración de Primavera derecha:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
</bean> 

<bean id="myDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
    <property name="transactionManager" ref="transactionManager"/> 
    <property name="target"> 
     <bean class="MyDaoImpl"> 
      <property name="dataSource" ref="dataSource"/> 
      <property name="sessionFactory" ref="sessionFactory"/> 
     </bean> 
    </property> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop> 
      <prop key="*">PROPAGATION_REQUIRED</prop> 
     </props> 
    </property> 
</bean> 

Esto supone que la parte de su JDBC DAO utiliza JdbcTemplate. Si no lo hace usted tiene algunas opciones:

  • Uso DataSourceUtils.getConnection (javax.sql.DataSource) para obtener una conexión
  • Envolver el origen de datos que se pasa a su DAO (pero no necesariamente el que uno pasar a SessionFactory) con un TransactionAwareDataSourceProxy

Este último es preferido ya que ocultó DataSourceUtils.getConnection dentro de la fuente de datos proxy.

Esta es, por supuesto, la ruta XML, debería ser fácil convertir esto en anotación.

2

El problema es que las operaciones en el motor Hibernate no dan como resultado en la ejecución inmediata de SQL. Puede activarlo manualmente llamando al flush en la sesión de Hibernate. Luego, los cambios realizados en hibernación serán visibles para el código SQL dentro de la misma transacción. Mientras lo hace DataSourceUtils.getConnection para obtener conexión de SQL, porque sólo entonces tendrá que correr en la misma transacción ...

En la dirección opuesta, esto es más complicado, porque tiene caché de nivel 1Nd (caché de sesión), y posiblemente también caché de segundo nivel. Con la memoria caché de segundo nivel, todos los cambios realizados en la base de datos serán invisibles para Hibernate, si la fila se almacena en caché, hasta que la caché caduque.

Cuestiones relacionadas