LazyInitializationException bei Spring / Hibernate

  • Themenstarter Themenstarter Konstantin Denerz
  • Beginndatum Beginndatum
K

Konstantin Denerz

Hallo,

ich bekomme folgende Exception beim Laden eines Objektes mit Hibernate(Spring):

Java:
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: de.tutorials.training.springLazyLoading.domain.Person.contacts, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
	at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
	at de.tutorials.training.springLazyLoading.domain.Main.main(Main.java:28)

Ich benutze Spring und Hibernate.
Ich habe ein Objekt person, das ein Attribut contacts vom Typ Set<Contact> hat.
Dieses person Objekt will ich nun speichern und dann wieder laden. Speichern funktioniert problemlos. Wenn ich dann aber die Kontakte der Person laden will(Lazy Loading) krieg ich die Exception.

Das person-Objekt:
Java:
package de.tutorials.training.springLazyLoading.domain;

import java.util.Set;

public class Person {
	private long id;

	private String firstName;

	private String lastName;

	private Set<Contact> contacts;

	public Set<Contact> getContacts() {
		return contacts;
	}

	public void setContacts(Set<Contact> contacts) {
		this.contacts = contacts;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public long getId() {
		return id;
	}

	private void setId(long id) {
		this.id = id;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

}
Mapping zu Person:
XML:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="de.tutorials.training.springLazyLoading.domain">
  <class name="Person">
  <id name="id" unsaved-value="0"><generator class="native"></generator> </id>
  <property name="firstName" type="string"></property>
  <property name="lastName" type="string"></property>
  <set name="contacts" cascade="all" lazy="true">
	  <key column="person_id"></key>
	  <one-to-many class="Contact"/>
  </set>
  </class>
</hibernate-mapping>
Das contact Objekt:
Java:
public class Contact {
	
	public Contact(String type, String value) {
		super();
		this.type = type;
		this.value = value;
	}

	public Contact() {
		super();
		// TODO Auto-generated constructor stub
	}

	private long id;

	private String type;

	private String value;

	public long getId() {
		return id;
	}

	private void setId(long id) {
		this.id = id;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

}

Mapping des Contacts:
XML:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="de.tutorials.training.springLazyLoading.domain">
  <class name="Contact">
  <id name="id" unsaved-value="0">
  <generator class="native"></generator>
  </id>
  <property name="type" type="string"></property>
  <property name="value" type="string"></property>
  </class>
</hibernate-mapping>

Hier die Serviceklassen:
Java:
//PersonAdministrationService
package de.tutorials.training.springLazyLoading.service;

import de.tutorials.training.springLazyLoading.domain.Person;
import de.tutorials.training.springLazyLoading.service.dao.IPersonDao;

public class PersonAdministrationService {
	private IPersonDao personDao;

	public IPersonDao getPersonDao() {
		return personDao;
	}

	public void setPersonDao(IPersonDao personDao) {
		this.personDao = personDao;
	}
	public void savePerson(Person person){
		this.getPersonDao().makePersistent(person);
	}
	public Person getPersonById(long id){
		return this.getPersonDao().getPersonById(id);
	}
}

// IPersonDao
package de.tutorials.training.springLazyLoading.service.dao;

import de.tutorials.training.springLazyLoading.domain.Person;

public interface IPersonDao {
	void makePersistent(Person person);
	Person getPersonById(long id);
}

//PersonDaoHibernateImpl
package de.tutorials.training.springLazyLoading.service.dao.internal;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import de.tutorials.training.springLazyLoading.domain.Person;
import de.tutorials.training.springLazyLoading.service.dao.IPersonDao;

public class PersonDaoHibernateImpl extends HibernateDaoSupport implements IPersonDao {

	public Person getPersonById(long id) {
		
		return (Person) this.getHibernateTemplate().get(Person.class, id);
	}

	public void makePersistent(Person person) {
		
		this.getHibernateTemplate().save(person);
	}

}

Und die Spring Konfiguration:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
	

	<bean name="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="conf/jdbcOracle.properties"/>
	</bean>
	
	
	<bean name="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
	
	
	 <bean name="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="myDataSource"></property>
		<!-- O/R-Mappings -->
		<property name="mappingResources">
			<list>
				<value>de/tutorials/training/springLazyLoading/domain/Contact.hbm.xml</value>
				<value>de/tutorials/training/springLazyLoading/domain/Person.hbm.xml</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.generate_statistics">false</prop>
				<prop key="hibernate.hbm2ddl.auto" >create-drop</prop>
			</props>	
		</property>
	</bean>
	
	
	<bean name="personDao" class="de.tutorials.training.springLazyLoading.service.dao.internal.PersonDaoHibernateImpl">
		<property name="sessionFactory" ref="mySessionFactory"/>
	</bean>
	
	 <bean name="myPersonAdministrationServiceTarget" class="de.tutorials.training.springLazyLoading.service.PersonAdministrationService">
	 	<property name="personDao" ref="personDao"></property>
	 </bean>
	 
	  <bean name="myTransactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="mySessionFactory"/>
	  </bean>	
	  
	 
	   
	   <bean id="myPersonAdministrationService"
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

		<property name="transactionManager" ref="myTransactionManager"/>
		<property name="target" ref="myPersonAdministrationServiceTarget" />
		<property name="transactionAttributes">
			<props>
				<prop key="save*">PROPAGATION_REQUIRED</prop>
				<prop key="get*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>

	</bean>
	  
</beans>

Die Main-Methode:
Java:
package de.tutorials.training.springLazyLoading.domain;

import java.util.HashSet;
import java.util.Set;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import de.tutorials.training.springLazyLoading.service.PersonAdministrationService;

public class Main {
		public static void main(String[] args){
			ApplicationContext applicationContext = new FileSystemXmlApplicationContext("conf/applicationContext.xml");
			PersonAdministrationService personAdministrationService= (PersonAdministrationService) applicationContext.getBean("myPersonAdministrationService");
			
			Person person =new Person();
			person.setFirstName("Konstantin");
			person.setLastName("Denerz");
			
			Set<Contact> contacs = new HashSet<Contact>();
			contacs.add(new Contact("email_privat","kde@tutorials.de"));
			person.setContacts(contacs);
			
			personAdministrationService.savePerson(person);
			
			System.out.println(personAdministrationService.getPersonById(1).getFirstName());
		
			System.out.println(personAdministrationService.getPersonById(1).getContacts().iterator().next().getValue());
			
		
		}
}
Hat jemand eine Idee warum das Lazy Loading nicht funktioniert?

Gruß Konstantin
 
Zuletzt bearbeitet von einem Moderator:
Warum die Exception geworfen wird, das weiß ich. Diese Session ist zu, aber wie löse ich es?
 
Hallo,

änder doch mal spaßeshalber das Mapping der Contacts in Person in:
XML:
<set fetch="join" name="contacts" cascade="all" lazy="false">
Das ändert das Ladeverhalten so, dass zum einen beim Laden einer Person auch die Kontakte sofort mitgeladen werden und zum anderen das keine zusätzlichen Selects sondern nur ein "großer" Join gemacht werden.

Ansonsten gibts eben die Möglichkeit die Collection (in einer entsprechenden ServiceMethode die noch in der Transaktion ist) mit Hibernate.initialize(person.getContacts()); explizit zu initialisieren.

Weiterhin wäre es denkbar eine (transaktionale) Service Methode zu haben die entsprechend alle Daten vorlädt.

Außerdem gäbs noch die Möglichkeit mit "langlaufenden" Transaktionen...

Gruß Tom
 
Zuletzt bearbeitet von einem Moderator:
Hallo zusammen,

ich habe das gleiche Problem. In anderen Foren hab ich gelesen, dass durch die Aufnahme der OpenSessionInViewFilter in der web.xml sichergestellt werden soll, dass für einen Request immer eine komplette Session verwendet wird. Das Funktioniert bei mir leider nicht. Anscheinend wird bei mir Spring zweimal initialisiert (?) und es existieren somit min. zwei Sessionfactorys, HibernateTemplates, etc. im laufenden System. Die beiden Initialisierungen werden durch zwei deployte Servlets (org.springframework.web.context.ContextLoaderServlet, org.apache.struts.action.ActionServlet) ausgelöst.

Leider bin ich relativ neu im Spring-Umfeld tätig und habe ein bestehendes System übernommen. Hier die wichtigsten Daten:

Spring 1.2.9, Hibernate 2.1

Auszug Web.xml
Code:
<servlet>
  <servlet-name>SpringContextServlet</servlet-name>
  <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
  <load-on-startup>2</load-on-startup>
 </servlet>
<servlet>
  <servlet-name>Struts Servlet</servlet-name>
  <!--servlet-class>org.apache.struts.action.ActionServlet; FrontController ist eine subclass von ActionServlet</servlet-class-->
  <servlet-class>biz.myera.era.web.servlet.FrontController</servlet-class>
  <init-param>
   <param-name>application</param-name>
   <param-value>ApplicationResources</param-value>
  </init-param>
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>
  <init-param>
   <param-name>debug</param-name>
   <param-value>6</param-value>
  </init-param>
  <init-param>
   <param-name>detail</param-name>
   <param-value>6</param-value>
  </init-param>
  <load-on-startup>3</load-on-startup>
 </servlet>

Auszug application-context.xml
Code:
	<!-- Hibernate SessionFactory Definition -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
		<property name="mappingResources">
			<list>				
				<!-- Business Object beans -->
...						
			</list>
		</property>		
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">false</prop>
				<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
				<prop key="hibernate.cache.provider_class">net.sf.hibernate.cache.HashtableCacheProvider</prop>
			</props>
		</property>	
		
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	
	<!-- Spring Data Access Exception Translator Defintion -->
	<bean id="jdbcExceptionTranslator" class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator"> 
		<property name="dataSource"><ref bean="dataSource"/></property> 
	</bean> 

	<!-- Hibernate Template Defintion -->
	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate"> 
		<property name="sessionFactory"><ref bean="sessionFactory"/></property> 
		<property name="jdbcExceptionTranslator"><ref bean="jdbcExceptionTranslator"/></property> 
	</bean> 

	<!-- Hibernate Transaction Manager Definition -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
		<property name="sessionFactory"><ref local="sessionFactory"/></property>
	</bean>

Schon mal vielen Dank für jegliche Unterstützung.

Best
Frank
 
Ich hatte das Problem ebenfalls innerhalb von JUnitTests mehrfach. Ich verwende JPA , Hibernate Entitymanager un Spring. Lösen konnte ich das Problem nur, weil ich zusätzlich AspectJ und LoadtimeWeaving vewende. damit habe ich die Möglichkeit auch ausserhalb von Springbeans in normalen Pojos Einfluss auf Transaktionen zu nehmen. Ich habe schicht und einfach über meine JUnitTests:
@Transactional(propagation=Propagation.NOT_SUPPORTED)
public void testEBankingAccountSaveGuard() throws AccountException {
...
} geschrieben und in meine aop.xml

<include within="*..itest.*" />

eingetragen.



Was ich als Propagation angebe ist relativ egal, Hauptsache Transactional steht da. Der commit detached die Entities und schließt offensichtlich die session. Für Webanwendungen gibt es ein Filter SessionInRequestfilter, das irgendwie in der web.xml eingetragen werden muss. Als Lösung ausserhalb von Webanwendungen fällt mir nur ein, auf Lazy-Loading zu verzichten, oder eben AspectJ und Transactional versuchen. Dadurch kommt man sowieso erst wieder zurück zur Objektorientierung ...

Spring (vom ursprünglichen Ansatz her) scheint mir da ein paar recht üble Schwächen vom Konzept her gehabt zu haben. Es gibt Dinge, die sich nicht mit Sigeltons und Factories alleine lösen lassen
 
Sorry, wenn ich so direkt bin, aber was du da schreibst, ist zum großteil Blödsinn. Wenn die Transaktionen richtig konfiguriert sind und das Hibernate Mapping korrekt ist, fliegen keine LazyLoadingExceptions.

Auch dein Arbeiten mit den JUnit Tests, zeugt davon, dass deine Annahmen Spring gegenüber auf Unwissenheit beruhen. Für Integrationstests gibt es AbstractTransactionalSpringContextTest, die dafür sorgt, dass jede Testmethode automatisch transaktional wird und am Ende ein Rollback ausgeführt wird.

Wie tut denn dein Code, wenn er produktiv ausgeführt wird? Wo ist denn dann dein Transaktionshandling, wenn der Unittest fehlt?

Ich hab einfach das Gefühl da werkelt jemand mit DIngen, die er nicht wirklich verstanden hat, macht dadurch Fehler und stellt dann die These auf "man häte vom Ansatz her ein paar recht üble Schwächen gehabt". Ich bitte dich, wenn Spring bei solch primitiven Dingen Schwächen hätte, wäre es wohl kaum so weit verbreitet wie es ist.

Vielleicht kannst du ja nochmal etwas Code und Konfiguration posten, die bei dir zu den LLEs führen. Vielleicht finden wir noch die ein oder andere Stelle, an der ein Fehlerchen zu finden ist. :)

Gruß und einen guten Rutsch...

REINHAUN!
 
Da will ich mal antworten,

AbstractDependencyInjectionSpringContextTests ist sicher eine schöne Sache, weil er mir das manuelle besorgen des ApplicationContests und das getBean abnimmt, was Transactionen angeht, spielt es keine Rolle, ob ich JUnitTest oder AbstractDependencyInjectionSpringContextTests oder was sonst nehme (Ich nutze aus Faulheit AbstractDependencyInjectionSpringContextTests)

Alle Mechanismen von Spring funktionieren nur mit managedBeans, d.h. dem was in der BeanKonfiguration konfiguriert ist. Alles was mit new oder sonst wie erzeugt wird, ist assen vor.

Ich rede auch von Schwächen, nicht von Fehlern. Martin Fowler beschreibt in seinem Antipattern "The anemic Domainmodell" die "Vorzüge" von J2EE. All das läßt sich auch mit Springerreiche. Wohl auch deshalb gibt es seit Spring 2.x Configurable. Geanu darum, weil es das gibt, bin ich heute überzeugt von Spring und genau aus dem Grund verwende ich es, wann immer möglich.

Es ist doch recht Klar, was passiert. JUnitTests (auch AbstractDependencyInjectionSpringContextTests ) sind keine managedBeans. Die Session bleibt genau so lange offen, wie die Methode auf dem BusinessBean (bei mir die Methode auf dem Pojo) ausgeführt wird. Greift man danach mit einem getter auf ein noch nicht aus der Datenbank gelesenes Object zu, ist die Session schon zu und das war es dann. Mit Transactional (Propagation.NOT_SUPPORTED) halte ich lediglich die Session solange offen, bis die Methode des JUnitTests zu ende ist (auf Transaktionsverhalten nehme ich in der BusinessMethode einfluss.

Ob ich Persitent Anemic Object oder Persistent Domain Object verwende ist meine Designentscheidung (ich nehme wenn immer möglich Persistent Domain Object . Noch bis Java EE 1.4 gab es laut Spezifikation von J2EE nur Persitent Anemic Object. Das das heute auch da anders ist, ist Verdienst von Spring und Co. Ebenfalls Verdienst von Spring und CO ist JPA und EJB3.0. Das was vorher war ist (nur meine persönliche Meinung) höchst suboptimal. HIer hat Spring einiges erreicht. Trotzdem. Zaubern kann auch Spring nicht und an nicht managedBeans kommt man nur mit AspectJ und vergleichbarem heran.

Wie ich es in Produktion löse:

1. LazyLoading wäre bei mir in der Tat entbehrlich

2. ich würde das SessionInRequestFilter ausprobieren

3. Ich würde die JSF-FormBean weaven und mit Transactional versehen
 
Na da haben wir doch schon etwas mehr fundiertes Futter um ins Gespräch zu kommen ;) ...

Da will ich mal antworten,

AbstractDependencyInjectionSpringContextTests ist sicher eine schöne Sache, weil er mir das manuelle besorgen des ApplicationContests und das getBean abnimmt, was Transactionen angeht, spielt es keine Rolle, ob ich JUnitTest oder AbstractDependencyInjectionSpringContextTests oder was sonst nehme (Ich nutze aus Faulheit AbstractDependencyInjectionSpringContextTests)

Ich habe nie von AbstractDependencyInjectionSpringContextTest (im folgenden ADISCT) geschrieben, sondern von AbstractTRANSACTIONALSpringContextTest (im folgenden ATSCT). Dieser ist für Integrationstests gedacht und umschließt jede Testmethode mit einer Transaktion, die im Normalfall nach der Ausführung gerollbackt wird.

Ich versteh halt den Sinn deines Unittests nicht wirklich. Entweder willst du deine Transaktionskonfiguration testen, dann reicht ADISCT indem du zusätzlich das Konfigurationsfile mit der Transaktionskonfiguration lädst und nach der Ausführung den Transaktionsmanager fragst, was er denn ausgeführt hat. Oder du machst nen Integrationstest auf DAOs z.B. an denen selbst keine Transaktionskonfiguration hängt und nutzt dann aber ATSCT.

Alle Mechanismen von Spring funktionieren nur mit managedBeans, d.h. dem was in der BeanKonfiguration konfiguriert ist. Alles was mit new oder sonst wie erzeugt wird, ist assen vor.

Das ist nicht wirklich korrekt. Es gibt seit Spring 2.0 @Configurable, wie du ja auch selbst unten schreibst. Zum anderen stellt sich mir die Frage, warum das Thema non-managedBeans so ein großes für dich ist. Ich vermute wegen der Unittests, aber dazu hab ich ja grad schon was geschrieben. Und Unittest heißt Unittest, weil da die Klasse als Unit getestet wird, dependencies gemockt usw. D.h. da spielt Transaktionalität keine Rolle. Und für Integrationstests, gibts wie gesagt ATSCT.

Ich rede auch von Schwächen, nicht von Fehlern. Martin Fowler beschreibt in seinem Antipattern "The anemic Domainmodell" die "Vorzüge" von J2EE. All das läßt sich auch mit Springerreiche. Wohl auch deshalb gibt es seit Spring 2.x Configurable. Geanu darum, weil es das gibt, bin ich heute überzeugt von Spring und genau aus dem Grund verwende ich es, wann immer möglich.
Hm...okay, ich versteh den Punkt, aber das hat doch mit Spring an sich nichts zu tun. Welches andere Programmiermodell unterstützt denn Objektorientierung besser? Überhaupt, OO hat doch keinen Wert an sich. Ich bin auch ein Freund von DDD ala Evans, aber das weit verbreitete Layering (und damit eher prozeduraler Code) hat sich schon bewährt und ist sicher nicht grundfalsch.

Es ist doch recht Klar, was passiert. JUnitTests (auch AbstractDependencyInjectionSpringContextTests ) sind keine managedBeans. Die Session bleibt genau so lange offen, wie die Methode auf dem BusinessBean (bei mir die Methode auf dem Pojo) ausgeführt wird. Greift man danach mit einem getter auf ein noch nicht aus der Datenbank gelesenes Object zu, ist die Session schon zu und das war es dann. Mit Transactional (Propagation.NOT_SUPPORTED) halte ich lediglich die Session solange offen, bis die Methode des JUnitTests zu ende ist (auf Transaktionsverhalten nehme ich in der BusinessMethode einfluss.

Siehe oben... genau das tut ATSCT.

Ob ich Persitent Anemic Object oder Persistent Domain Object verwende ist meine Designentscheidung (ich nehme wenn immer möglich Persistent Domain Object . Noch bis Java EE 1.4 gab es laut Spezifikation von J2EE nur Persitent Anemic Object. Das das heute auch da anders ist, ist Verdienst von Spring und Co. Ebenfalls Verdienst von Spring und CO ist JPA und EJB3.0. Das was vorher war ist (nur meine persönliche Meinung) höchst suboptimal. HIer hat Spring einiges erreicht. Trotzdem. Zaubern kann auch Spring nicht und an nicht managedBeans kommt man nur mit AspectJ und vergleichbarem heran.
Ich glaub nicht, dass die J2EE Spech dir vorgibt oder vorgegeben hat, welches Pattern du für deine Domäne implentieren sollst. Wie du ja selber sagst, geht J2EE mit Spring locke ohne EJB und damit also auch DDD. Oder zwingt dich jemand EntityBeans bzw. JPA zu benutzen, ausser dein Chef vielleicht?

Zum Thema managed Beans hab ich ja schon was geschrieben. Und AspectJ ist ja auch nicht grad der Vorort der Hölle, alles halb so schlimm.

Wie ich es in Produktion löse:

1. LazyLoading wäre bei mir in der Tat entbehrlich

2. ich würde das SessionInRequestFilter ausprobieren

3. Ich würde die JSF-FormBean weaven und mit Transactional versehen
Ich meine eher, wie deine Transaktionskonfiguration bezgl. deines zu testenden Services gemacht ist. Mit ATSCT sollte es wie gesagt reichen, einfach für diese Testklasse die Transaktionskonfiguration nicht zu laden und das Standardverhalten von Spring zu nutzen.

Gruß und ein frohes Neues...

REINHAUN
 
Es ist schon richtig, das Objektorientierung an sich nur ein technisches Paradigma ist und an sich noch keinen Wert darstellt. Und falsch ist auch, das sich nicht alles auch mit Sigeltons und Factories lösen läßt: Es muss sich lösen lassen, weil sich alles auch in einer prozeduralen Sprache wie C lösen ließe aber mit zum Teil auch üblen Folgen. Niemand zwingt mich derzeit zu irgendetwas. Man muss nur gewisse Dinge "ertragen", weil Tatsachen vorhanden sind (geschaffen wurden) mit denen man (oder jemand anderer) sich dann arangieren muss ...

Der JUnitTest ist doch gar nicht das Problem: Irgendwo stand etwas von Sping 1.2.x und Transactionales Verhalten wird in Spring doch wohl über Aspekte dazukonfiguriert? Wie sonst auch? Da wollte ich eigentlich lediglich anmerken, dass sich durchaus Zenarien ergeben können das jemand zugreift, wenn der Interceptor die Session geschlossen hat. Spring 1.x hat nichts von den Möglichkeiten über die wir jetzt diskutieren wollen.


Mein Transaktionsverhalten will ich ausschließlich über Transactional-Annotation, weil mir xml-Konfigfiles von Hause aus zu wieder sind

....

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="oracle"></property>
</bean>

<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf" >
<property name="transactionManager" ref="jpaTransactionManager" />
</bean>

Die BusinessMethode definiert das Transactionsverhalten, der DAO schon soetwas wie ein Defaultverhalten, das die Business-Methode aber in jedem Fall überschreibt. Der JUnitTest soll zeigen, ob meine Werke arbeiten und mir helfen sie zu erstellen (besonders das letzte). Transaktionsverhalten hat darin rein gar nichts 8nach der THerorie) zu suchen

Die Diskussionen sind aber jetzt schon am eigentlichen Thema vorbei fürchte ich und für den Rest der Welt vermutlich nicht allzu spannend.

Auch gebe ich zu, das für mich die direkte Verwendung von Hibernate derzeit Geschichte ist, ich also nicht sehr tief mit deren Konfiguration mehr vertraut bin Zugegeben rein spekulativ, weil ich glaube, das sich in Zukunft vielleicht noch etwas anderes neben Hibernate entwickelt, das einmal eine Alternative darstellen könnte und ebenfalls die JPA Schnittstelle bedient. Und irgendwann wird sich auch Spring erledigen, glaube ich. Derzeit benutzen wir es doch eigentlich nur, um Mittel zur Verfügung zu haben, die in Java fehlen und die wir dann durch xml Konfiguration (und Runtime-Exceptions) erkaufen. Auch dabei ist nur wichtig, das wir Strategie gegenüber Vererbung bevorzugen (in gewissem Rahmen), derzeit tun wir das, bis wir etwas besseres oder anderes haben. Die Frameworks sind mir egal. Die sind vergänglich und austauschbar, wichtig sind einzig und alleine die Prinzipien. Spring ist derzeit auch mein Favorit, aber das wird sich vermutlich ändern. J2EE ist Darwinismus pur. Spannend ist, was am Ende wirklich das beste ist. Und um das zu beurteilen, muss ich auch die Schwächen kritisch sehen.

Ich glaube, das am Ende Dependency Injection und AOP in eine Sprache x eingehen werden. Ich glaube auch, das sich der ganze xml-Konfigurationsmist erledigen wird und ebenfalls integraler Bestandteil in Form von Annotations (oder vergleichbarem) werden wird. Und zurück zum Ausgang: Objektorientierung ist kein Wert an sich: Aber Evolution als solche ist eines der höchsten Werte: Alternative wäre es an Stelle dieser Diskussionen vor Säbelzahntigern auf Bäume zu fliehen... Auch dieser Vergleich hat eine gewisse Arroganz, indem er unterstellt, das die Evolution schon ihre Vollendung gefunden hätte, was relatistisch betrachtet wohl naiv wäre

Spring ist also vermutlich nur ein Zwischenschritt hin zu einer neuen Sprache oder hin zu einer Veränderung bzw. Anpassung der Pattern und Idiome und wird am Ende wegoptimiert werden.

Demnächst wird es ein Spring geben, das ganz ohne Konfigfiles auskommt und rein auf Basis von Annotions arbeitet.

Das beste OO-Modell ist das von Java, C++ etc ohne alle mehr oder weniger selbstgemachten "Antipattern" , die nur versuchen wieder C daraus zu machen !
 
Ich machs kurz: Transaktionales verhalten von JUnit Testmethoden ist mit ATSCT möglich und die Klasse gibt es laut Api Doc seit 1.1.1. Das programmierst du von Hand nach... Deswegen war ich halt arg verwirrt...

Gruß
Ollie
 
Zurück