DarthShader
Erfahrenes Mitglied
Hallo zusammen,
ich habe ein Problem mit Spring / AOP in Kombination mit Hibernate und Transaktionen. Anscheinend werden keine Transaktionen gestartet, und ich kann mir nicht erklären, warum das so ist.
Hier erstmal die "Vorgeschichte":
Dies ist eine Service Klasse, deren Methode soll mit einer Transaktion gesichert werden:
So sieht das DAO aus:
Und nun, wie ich den Spring context bezüglich der DB konfiguriere:
Und zu guter letzt die Definition von AOP, um das transaktionale Verhalten festzulegen:
Wenn ich den Code aufrufe, dann erhalte ich ganz oben, wo ich es im Kommentar angegeben habe, eine Exception, die besagt, dass er "sysConfig.getAddresses();" nicht ausführen kann:
Das ist auch logisch, denn es handelt sich ja um ein von Hibernate erstelltes Proxy-Objekt. Die Objekte werden aus der DB lazy geladen, d.h. "getAddresses()" führt zu einer weiteren Anfrage an die DB. In dem moment ist die Hibernate Session aber gar nicht mehr da, da ich im DAO ja das "getHibernateTemplate().get" verwende.
Aber: eigentlich sollte die Methode "ServerRemoteService.getSystemConfiguration()" doch in einer Transaktion ablaufen. Täte sie das, würde die Hibernate Session über den DAO-Aufruf hinaus doch offen bleiben, und der Aufruf von "sysConfig.getAddresses()" sollte doch klappen. Dennoch sagt er mir, in der Zeile sei keine Session mehr offen.
Deshalb vermute ich, dass meine AOP Konfig mit der Transaktion nicht greift. Die ganzen Package-Angaben und Pfade habe ich natürlich schon doppelt und dreifach geprüft
Hat irgendjemand eine Idee, wieso das nicht funktioniert?
Über Eure Hilfe würde ich mich sehr freuen
Vielen Dank!
ich habe ein Problem mit Spring / AOP in Kombination mit Hibernate und Transaktionen. Anscheinend werden keine Transaktionen gestartet, und ich kann mir nicht erklären, warum das so ist.
Hier erstmal die "Vorgeschichte":
Dies ist eine Service Klasse, deren Methode soll mit einer Transaktion gesichert werden:
Java:
public class ServerRemoteService {
public SysConfig getSystemConfiguration() {
SysConfig sysConfig = sysConfigDao.getSysConfig( 1 );
if ( sysConfig == null )
return null;
// Tue etwas mit der sysConfig
sysConfig.getAddresses(); // Exception wegen Lazy Loading, da keine Session mehr offen ist!
return sysConfig;
}
So sieht das DAO aus:
Java:
public class HibernateSysConfigDaoImpl extends HibernateDaoSupport implements SysConfigDao {
@Override
public SysConfig getSysConfig( Serializable id ) {
return (SysConfig)getHibernateTemplate().get( SysConfig.class, id );
}
}
Und nun, wie ich den Spring context bezüglich der DB konfiguriere:
XML:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="acquireRetryAttempts" value="1" />
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/foo" />
<property name="user" value="foo" />
<property name="password" value="foo" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<value>
hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql = false
hibernate.format_sql = true
</value>
</property>
<property name="packagesToScan">
<list>
<value>de.foo.domain.**.*</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Und zu guter letzt die Definition von AOP, um das transaktionale Verhalten festzulegen:
XML:
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="REQUIRED" />
<tx:method name="find*" read-only="true" propagation="REQUIRED" />
<tx:method name="*" read-only="false" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serverRemoteServiceMethods" expression="execution(* de.foo.server.service.ServerRemoteService*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serverRemoteServiceMethods" />
</aop:config>
Wenn ich den Code aufrufe, dann erhalte ich ganz oben, wo ich es im Kommentar angegeben habe, eine Exception, die besagt, dass er "sysConfig.getAddresses();" nicht ausführen kann:
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
de.foo.domain.sysconfig.SysConfig.addresses, no session or session was closed
Das ist auch logisch, denn es handelt sich ja um ein von Hibernate erstelltes Proxy-Objekt. Die Objekte werden aus der DB lazy geladen, d.h. "getAddresses()" führt zu einer weiteren Anfrage an die DB. In dem moment ist die Hibernate Session aber gar nicht mehr da, da ich im DAO ja das "getHibernateTemplate().get" verwende.
Aber: eigentlich sollte die Methode "ServerRemoteService.getSystemConfiguration()" doch in einer Transaktion ablaufen. Täte sie das, würde die Hibernate Session über den DAO-Aufruf hinaus doch offen bleiben, und der Aufruf von "sysConfig.getAddresses()" sollte doch klappen. Dennoch sagt er mir, in der Zeile sei keine Session mehr offen.
Deshalb vermute ich, dass meine AOP Konfig mit der Transaktion nicht greift. Die ganzen Package-Angaben und Pfade habe ich natürlich schon doppelt und dreifach geprüft
Hat irgendjemand eine Idee, wieso das nicht funktioniert?
Über Eure Hilfe würde ich mich sehr freuen
Vielen Dank!
Zuletzt bearbeitet von einem Moderator: