Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich hab meine DAOs Impl mit Hibernate realisiert und mach mich nur mit Spring an die Service Schicht, wie realisiert man am besten Transaktionen in der Service Schicht?
Der Code ist nicht abhängig von Spring, aber Du hast halt die Imports der Annotations drin. Wenn Du das nicht willst, kannst Du das gleiche auch mit XML Konfiguration erreichen. Wie das geht steht in der Spring Doku.
Der Code ist nicht abhängig von Spring, aber Du hast halt die Imports der Annotations drin. Wenn Du das nicht willst, kannst Du das gleiche auch mit XML Konfiguration erreichen. Wie das geht steht in der Spring Doku.
Das habe ich nicht geschrieben. Springs HibernateTemplate ist ab Hibernate 3.0 nicht mehr nötig! Denn Hibernate hat nun durch den Current Session Context ein eigenes Session Management. Das hat früher Spring übernommen.
Spring ist aber immernoch sinnvoll für den Hibernate-Einsatz und übernimmt dann folgende Aufgaben:
Das habe ich nicht geschrieben. Springs HibernateTemplate ist ab Hibernate 3.0 nicht mehr nötig! Denn Hibernate hat nun durch den Current Session Context ein eigenes Session Management. Das hat früher Spring übernommen.
Spring ist aber immernoch sinnvoll für den Hibernate-Einsatz und übernimmt dann folgende Aufgaben:
Noch eine Frage was ist besser die Annotation an das Interface oder an die Implementierung?
Also ich habs mal so versucht
Java:
public interface KundenService {
@Transactional(propagation = Propagation.REQUIRED)
public Kunde searchKundeById(Long id);
}
Java:
public class KundenServiceImpl implements KundenService{
private KundenDAO kundenDAO;
public void setKundenDAO(KundenDAO kundenDAO) {
this.kundenDAO = kundenDAO;
}
@Override
public Kunde searchKundeById(Long id) {
return kundenDAO.getKundeById(id);
}
public KundenDAO getKundenDAO() {
return kundenDAO;
}
}
Java:
public interface KundenDAO {
@Transactional(propagation = Propagation.MANDATORY)
Kunde getKundeById(Long id);
}
Java:
public class HibernateKundenDAOImpl implements KundenDAO{
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public Kunde getKundeById(Long id) {
return (Kunde) sessionFactory.getCurrentSession().load(Kunde.class, id);
}
}
Java:
org.hibernate.HibernateException: load is not valid without active transaction
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338)
at $Proxy7.load(Unknown Source)
at dao.impl.HibernateKundenDAOImpl.getKundeById(HibernateKundenDAOImpl.java:27)
at service.impl.KundenServiceImpl.searchKundeById(KundenServiceImpl.java:42)
at kunde.KundenServiceTest.testCreateKunde(KundenServiceTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Normal packt man die Annotation an die Implementierung, da es ja auch Implementierungen ohne benötigte Transaktion geben könnte. Die Spring-Doku sagt das aber auch mein ich
Hast du das @Transactional denn jetzt an die Methode gepackt? Die Fehlermeldung kam vermutlich, weil das Interface annotiert war aber die Implementierung nicht, damit gab es keine echte Transaktion.
Hast du das @Transactional denn jetzt an die Methode gepackt? Die Fehlermeldung kam vermutlich, weil das Interface annotiert war aber die Implementierung nicht, damit gab es keine echte Transaktion.
Nee noch nicht... Des war nur darauf bezogen weil du gesagt hast für findXbyY braucht man keine Transaktion deshalb.
Die Fehlermeldung kam auch wo ich das @Transactional an die Implementierung gemacht hab.
Jetzt versuch ich es noch an der Methode vielleicht klappt das =)...
Aber ich dachte wenn ich das @Transactional an die Implementierung mache dann zählt das für alle Methoden.
<context:annotation-config/>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager" />
<!-- a PlatformTransactionManager is still required -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
public class KundenServiceTest extends TestCase {
public void testCreateKunde() throws Exception {
ClassPathResource res = new ClassPathResource("applicationContext.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
KundenService kundenService = factory.getBean("kundenService", KundenService.class);
Kunde kunde = kundenService.searchKundeById(Long.valueOf(1));
assertEquals(Long.valueOf(1), kunde.getId());
}
}
Service Klasse
Java:
public class KundenServiceImpl implements KundenService{
private KundenDAO kundenDAO;
@Transactional(propagation = Propagation.REQUIRED)
@Override
public Kunde searchKundeById(Long id) {
return kundenDAO.getKundeById(id);
}
public void setKundenDAO(KundenDAO kundenDAO) {
this.kundenDAO = kundenDAO;
}
public KundenDAO getKundenDAO() {
return kundenDAO;
}
}
Java:
public class HibernateKundenDAOImpl implements KundenDAO{
@Autowired
private SessionFactory sessionFactory;
// public SessionFactory getSessionFactory() {
// return sessionFactory;
// }
//
// public void setSessionFactory(SessionFactory sessionFactory) {
// this.sessionFactory = sessionFactory;
// }
@Transactional(propagation = Propagation.MANDATORY)
@Override
public Kunde getKundeById(Long id) {
return (Kunde) sessionFactory.getCurrentSession().load(Kunde.class, id);
}
}
Das hier hab ich auch schon versucht
[XML]
<bean id="txManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
[/XML]
Unterschied versteh ich noch nicht ganz... aber klappt mit beidem net :bahnhof:
Das sieht doch schon sehr vielversprechend (äh fehlerhaft aus )
Du Initialisierst Spring mit der falschen Art BeanFactory. Um Annotations zu nutzen musst du meines Wissens nach keine einfache BeanFactory sondern einen ausgewachsenen ApplicationContext nutzen. Diesen kannst du initialisieren wie in der Spring-Doku erklärt: Chapter3.The IoC container
Damit dürften sich dann gleiche beide Probleme erledigt haben. Ohne ApplicationContext gibt es nämlich auch keine AOP Unterstützung.
PS: Falls du AOP nutzen willst musst du eventuell noch den Java-Agent von Spring einsetzen.
Das sieht doch schon sehr vielversprechend (äh fehlerhaft aus )
Du Initialisierst Spring mit der falschen Art BeanFactory. Um Annotations zu nutzen musst du meines Wissens nach keine einfache BeanFactory sondern einen ausgewachsenen ApplicationContext nutzen. Diesen kannst du initialisieren wie in der Spring-Doku erklärt: Chapter3.The IoC container
Damit dürften sich dann gleiche beide Probleme erledigt haben. Ohne ApplicationContext gibt es nämlich auch keine AOP Unterstützung.
PS: Falls du AOP nutzen willst musst du eventuell noch den Java-Agent von Spring einsetzen.
public class KundenServiceTest extends TestCase {
public void testCreateKunde() throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml"});
KundenService kundenService = context.getBean("kundenService", KundenService.class);
Kunde kunde = kundenService.searchKundeById(Long.valueOf(1));
assertEquals(Long.valueOf(1), kunde.getId());
}
}
Fehler
Java:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0': BeanPostProcessor before instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:446)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:289)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:286)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:188)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:543)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:730)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:387)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
at kunde.KundenServiceTest.testCreateKunde(KundenServiceTest.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.isInfrastructureClass(AbstractAutoProxyCreator.java:384)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:278)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:831)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:803)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:440)
... 29 more
Caused by: java.lang.ClassNotFoundException: org.aopalliance.aop.Advice
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
... 34 more
Das ist mir bewusst ...
ich hab mit die aopalliance.jar runtergeladen aber die Klasse ist nicht dabei, darum frag ich mich woher ich die bekomm?
EDIT: ok ich hab die com.springsource.org.aopalliance-1.0.0 gefunden =)
Wir kommen näher dran
Java:
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (socket creation error)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:241)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:336)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:102)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy10.searchKundeById(Unknown Source)
at kunde.KundenServiceTest.testCreateKunde(KundenServiceTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (socket creation error)
at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1228)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:884)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:203)
... 26 more
Caused by: java.sql.SQLException: socket creation error
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.jdbcConnection.<init>(Unknown Source)
at org.hsqldb.jdbcDriver.getConnection(Unknown Source)
at org.hsqldb.jdbcDriver.connect(Unknown Source)
at org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:294)
at org.apache.commons.dbcp.BasicDataSource.validateConnectionFactory(BasicDataSource.java:1340)
at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1224)
... 28 more
[XML]
<!-- a PlatformTransactionManager is still required
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>-->
Also wenn ich den HibernateTransactionManager verwende bekomme ich die Fehlermeldung weg...
Versteh den unterschied zwischen den beiden noch nicht ganz?
Hab so verstanden der DataSourceTransactionManager ist nur dafür das wenn ich per JDBC ohne Hibernate zugriff habe. Und der andere ist notwendig damit ich die sessionFacotry eine Session anlegt.
Hab ich dann die ganze Anwendung nur eine Session und eine SessionFactory?
Also die sessionFacotry ist nimmer null also ein Problem gelöst, aber
bekomm immer noch die Fehlermeldung
Java:
org.hibernate.HibernateException: load is not valid without active transaction
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338)
at $Proxy12.load(Unknown Source)
at dao.impl.HibernateKundenDAOImpl.getKundeById(HibernateKundenDAOImpl.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy9.getKundeById(Unknown Source)
at service.impl.KundenServiceImpl.searchKundeById(KundenServiceImpl.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy10.searchKundeById(Unknown Source)
at kunde.KundenServiceTest.testCreateKunde(KundenServiceTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
<context:annotation-config/>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager" />
Doch z.B. erstmal ohne AOP. Langsam nach und nach alles einbauen.
Abgesehen davon habe ich außer dem JAR der AOP-Alliance und Spring-AOP (inkl CGLIB) keine weiteren Abhängigkeiten für AOP. Und die obige Fehlermeldung zeigt eindeutig eine Class aus dem Alliance JAR, also vielleicht falsche Version des JAR?
Wie gesagt, bei Spring ist es nie falsch sich gleich mit Maven anzufreunden, da hast du solche Probleme mit fehlenden Abhängigkeiten nicht.
Abgesehen davon habe ich außer dem JAR der AOP-Alliance und Spring-AOP (inkl CGLIB) keine weiteren Abhängigkeiten für AOP. Und die obige Fehlermeldung zeigt eindeutig eine Class aus dem Alliance JAR, also vielleicht falsche Version des JAR?
Welche jars hast du den dann kann ich mal vergleichen ob ich die richtigen hab??
Ja es hat eigentlich soweit alles mit Spring geklappt, nur die Transaktionen wollen nicht so richtig.
Und so wie ich das verstanden hab brauch ich fürs Declarative transaction management AOP.
Oder meinst du ich soll erstmal versuchen eine Transaktion programmatisch anzulegen mit dem PlatformTransactionManager???
Ich hab keine Ahnung wie das mit Hibernate aussehen muss. Bei JPA ist das ganz anders (siehe unten):
[xml] <tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
Die Abhängigkeiten kann ich dir nicht genau nennen, weil Maven die verwaltet. Abgesehen davon nutze ich teils, SpringSource Repackaged Packages, weil wir OSGi nutzen.
Ich hab keine Ahnung wie das mit Hibernate aussehen muss. Bei JPA ist das ganz anders (siehe unten):
[xml] <tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
Die Abhängigkeiten kann ich dir nicht genau nennen, weil Maven die verwaltet. Abgesehen davon nutze ich teils, SpringSource Repackaged Packages, weil wir OSGi nutzen.
Ah ok... Ja hau ich wohl AOP nochmal raus und mach das Chapter 8 und 9 nochmal durch... Habs zwar schon paar mal gelesen ob ich was finde, was falsch ist ...
Da ich das nur daheim zum Lernen nehm wollte ich mich jetzt nicht noch in Maven einarbeiten und das aufsetzen. Aber kommt noch, man kann ja nicht alles aufeinmal machen ...
Deine Konfiguration mit dem HibernateTransactionManager ist richtig, wenn Du mit SessionFactory und Session arbeitest. Das was Noctarius schreibt bezieht sich auf den reinen JPA-Weg, also ohne SessionFactory und Session, stattdessen mit EntityManagerFactory und EntityManager. Du musst Dich für einen der beiden Wege entscheiden und darfst die Konfiguration nicht mischen.
Wichtig ist, dass Du - da Du offenbar JUnit 3.8 verwendest - Deine Tests von
Code:
AbstractTransactionalJUnit38SpringContextTests
ableitest, damit Spring vor dem Test eine Transaktion aufmacht und nach dem Test ein Rollback macht.
Deine Konfiguration mit dem HibernateTransactionManager ist richtig, wenn Du mit SessionFactory und Session arbeitest. Das was Noctarius schreibt bezieht sich auf den reinen JPA-Weg, also ohne SessionFactory und Session, stattdessen mit EntityManagerFactory und EntityManager. Du musst Dich für einen der beiden Wege entscheiden und darfst die Konfiguration nicht mischen.
Wichtig ist, dass Du - da Du offenbar JUnit 3.8 verwendest - Deine Tests von
Code:
AbstractTransactionalJUnit38SpringContextTests
ableitest, damit Spring vor dem Test eine Transaktion aufmacht und nach dem Test ein Rollback macht.
Das werd ich mal versuchen und vergleichen =)...
2 Fragen:
1. Was macht <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> genau???
2. Was steht in der xml(@ContextConfiguration(locations={"/testContext.xml"}) )
Hatte was von JUnit 3.8 im Stacktrace oben gelesen, daher die Vermutung. Wenn Du JUnit 4 benutzt, dann nimm die Testklasse
Code:
AbstractTransactionalJUnit4SpringContextTests
.
zu 1.) Die Bean übersetzt Hibernate Exceptions in DataAccessExceptions. Das ist eine Persistenz-unabhängige Exception Hierarchie. Die Exceptions sind häufig viel aussagefähiger als die reinen Hibernate oder SQL Exceptions.
zu 2.) testContext.xml beinhaltet mindestens genau das, was ich oben an Konfiguration gepostet habe.
Hatte was von JUnit 3.8 im Stacktrace oben gelesen, daher die Vermutung. Wenn Du JUnit 4 benutzt, dann nimm die Testklasse
Code:
AbstractTransactionalJUnit4SpringContextTests
.
zu 1.) Die Bean übersetzt Hibernate Exceptions in DataAccessExceptions. Das ist eine Persistenz-unabhängige Exception Hierarchie. Die Exceptions sind häufig viel aussagefähiger als die reinen Hibernate oder SQL Exceptions.
zu 2.) testContext.xml beinhaltet mindestens genau das, was ich oben an Konfiguration gepostet habe.
Ja dachte ist praktischer das Interface zu defnieren und die Implmentation im XML festzulegen...
Aber gut stimmt man sollte für jede Implmentation einen Test haben.
19.11.2009 23:38:09 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [testContext.xml]
19.11.2009 23:38:09 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@78aa80: startup date [Thu Nov 19 23:38:09 CET 2009]; root of context hierarchy
19.11.2009 23:38:09 org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from class path resource [jdbc.properties]
19.11.2009 23:38:10 org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'dataSource' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
19.11.2009 23:38:10 org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory
19.11.2009 23:38:11 org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'sessionFactory' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
19.11.2009 23:38:11 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@fccada: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,dataSource,sessionFactory,transactionManager,kundenDAO,kundenServiceImpl]; root of factory hierarchy
19.11.2009 23:38:12 org.springframework.orm.hibernate3.HibernateTransactionManager afterPropertiesSet
INFO: Using DataSource [org.apache.commons.dbcp.BasicDataSource@54864c] of Hibernate SessionFactory for HibernateTransactionManager
19.11.2009 23:38:12 org.springframework.test.context.TestContextManager prepareTestInstance
SCHWERWIEGEND: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@128d900] to prepare test instance [kunde.KundenServiceTest@be95bf]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kunde.KundenServiceTest': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private service.impl.KundenServiceImpl kunde.KundenServiceTest.kundenService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [service.impl.KundenServiceImpl] is defined: Unsatisfied dependency of type [class service.impl.KundenServiceImpl]: expected at least 1 matching bean
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:280)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1011)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:333)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private service.impl.KundenServiceImpl kunde.KundenServiceTest.kundenService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [service.impl.KundenServiceImpl] is defined: Unsatisfied dependency of type [class service.impl.KundenServiceImpl]: expected at least 1 matching bean
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:497)
at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:277)
... 26 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [service.impl.KundenServiceImpl] is defined: Unsatisfied dependency of type [class service.impl.KundenServiceImpl]: expected at least 1 matching bean
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:751)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:666)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:468)
... 28 more
19.11.2009 23:38:12 org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@78aa80: startup date [Thu Nov 19 23:38:09 CET 2009]; root of context hierarchy
19.11.2009 23:38:12 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@fccada: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,dataSource,sessionFactory,transactionManager,kundenDAO,kundenServiceImpl]; root of factory hierarchy
19.11.2009 23:38:12 org.springframework.orm.hibernate3.AbstractSessionFactoryBean destroy
INFO: Closing Hibernate SessionFactory
Test
Java:
@ContextConfiguration(locations={"/testContext.xml"})
@TransactionConfiguration(defaultRollback=true)
public class KundenServiceTest extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
private KundenServiceImpl kundenService;
@Test
public void testSerchKunde() throws Exception {
Kunde kunde = kundenService.searchKundeById(Long.valueOf(1));
assertEquals(Long.valueOf(1), kunde.getId());
}
}
<!-- Services Mit und ohne diese Zeile versucht -->
<bean id="kundenServiceImpl" class="service.impl.KundenServiceImpl"/>
</beans>
[/XML]
Die 2 Nachrichten machen mich auch noch stutzig
[XML]
INFO: Loading properties file from class path resource [jdbc.properties]
19.11.2009 23:38:10 org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'dataSource' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
19.11.2009 23:38:10 org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory
19.11.2009 23:38:11 org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'sessionFactory' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[/XML]
Eigentlich nutzt man das Interface bei WireByType. Ergo im Sourcecode das Interface verwenden und im ApplicationContext.xml die Implementierung als Bean erstellen lassen. Spring nutzt dann automatisch die Implementierung beim Binden der Interfaces.