Problem z Spring + Hibernate - Bean is not writable

0

Witam,
Próbuję połączyć Springa z Hibernate. Zapisuję potrzebne beany w xml, tak jak poniżej:

<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
		<property name="configLocation" value="classpath:META-INF/hibernate.cfg.xml" />
	</bean>

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

Następnie uruchamiam aplikację na Apache-u i dostaję następujący komunikat błędu:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in ServletContext resource [/WEB-INF/web-data.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'sessionFactory' of bean class [org.springframework.orm.jpa.JpaTransactionManager]: Bean property 'sessionFactory' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

Orientujecie się w czym może leżeć problem?
Z góry dzięki za pomoc !

0

Mieszasz dwie różne rzeczy. Zabawki z JPA nie łączą się bezpośrednio z zabawkami z Hibernate (bo przecież mógłbyś chcieć podmienić dostawcę JPA na innego niż Hibernate).
Tak więc albo robisz to tak:

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="persistenceUnitName" value="cośtam" />
    <property name="packagesToScan">
    <list>
       <value>jpa/config</value>
    </list>
    </property>
    <property name="jpaVendorAdapter">
       <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
          <property name="database" value="HSQL" />
       </bean>
    </property>
 </bean>
 
 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
 </bean>

Albo tak:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                <property name="dataSource" ref="dataSource" />
                <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
                <property name="configLocation" value="classpath:META-INF/hibernate.cfg.xml" />
</bean>
 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
     <property name="sessionFactory" ref="sessionFactory"/>
</bean>
0

Rozumiem, wiele mi to wyjaśniło, dzięki! Napotkałem teraz trochę inny problem. Jak pisałem wcześniej posiadam:

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

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
		<property name="configLocation" value="classpath:META-INF/hibernate.cfg.xml" />
	</bean>

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

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

	<tx:annotation-driven transaction-manager="transactionManager" /> 

i dostaje teraz błąd:

24.07.2012 20:53:01 ERROR (ContextLoader.java:220) - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'accountDaoBean': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/web-data.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.persistence.spi.PersistenceUnitInfo.getValidationMode()Ljavax/persistence/ValidationMode;
	 

Czy to znowu coś z JPA ?

0

No nadal mieszasz JPA z natywnym Hibernate a to jest bardzo zły pomysł.
Jeśli chodzi o sam błąd to google zwraca kupę wyników z podobnymi błędami, poczytaj moze znajdziesz tam odpowiedź.

0

Problem wynika z tego, że mam wiele pakietów javax.persistance. Tak wygląda wynik komendy mvn dependency:tree :

 [INFO] +- postgresql:postgresql:jar:8.4-701.jdbc4:compile
[INFO] +- org.hibernate:hibernate-core:jar:3.6.6.Final:compile
[INFO] |  +- antlr:antlr:jar:2.7.6:compile
[INFO] |  +- commons-collections:commons-collections:jar:3.1:compile
[INFO] |  +- dom4j:dom4j:jar:1.6.1:compile
[INFO] |  \- javax.transaction:jta:jar:1.1:compile
[INFO] +- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.0.Final:provided (scope not updated to compile)
[INFO] +- org.hibernate:hibernate-annotations:jar:3.4.0.GA:compile
[INFO] |  \- org.hibernate:ejb3-persistence:jar:1.0.2.GA:compile
[INFO] +- org.hibernate:hibernate-commons-annotations:jar:3.3.0.ga:compile
[INFO] |  +- org.hibernate:hibernate:jar:3.2.1.ga:compile
[INFO] |  |  +- net.sf.ehcache:ehcache:jar:1.2.3:compile
[INFO] |  |  +- asm:asm-attrs:jar:1.5.3:compile
[INFO] |  |  \- asm:asm:jar:1.5.3:compile
[INFO] |  \- javax.persistence:persistence-api:jar:1.0:compile
[INFO] +- org.hibernate:hibernate-entitymanager:jar:3.6.6.Final:compile
[INFO] |  +- cglib:cglib:jar:2.2:compile
[INFO] |  \- javassist:javassist:jar:3.12.0.GA:compile
[INFO] \- org.hibernate:hibernate-validator:jar:4.1.0.Final:compile

Problem wynikał z tego, że zależności korzystało z wielu persisntace o różnych wersjach. Usunąłem zależność hibernate-commons-annotations i hibernate-annotations, bo chyba wystarczy jak będe miał dopięte:
[INFO] +- org.hibernate.javax.persistence:hibernate-jpa-2.0-api🫙1.0.0.Final:provided (scope not updated to compile)

Czy tak będzie ok ?

0

A na jakim serwerze to uruchamiasz? Bo wiesz że musisz mieć w zależnościach też jakąś implementację JPA? Samo api nie wystarczy. Jeśli korzystasz z jakiegoś serwera aplikacyjnego (JBoss, Glassfish, WebSphere, WebLogic etc) to nie ma problemu, ale jeśli odpalasz to na Tomcacie albo Jettym to musisz tą implementację tam wrzucić.

0

Odpalam na Tomcacie i udało mi się postawić aplikację.
Co powinienem jeszcze dodać ?

Czy mógłbyś stweirdzić, że teraz dobrze ustawiłem wszystko? :

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

	<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/testDB"
		cache="true" resource-ref="true" lookup-on-startup="false"
		proxy-interface="javax.sql.DataSource" />

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

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
		<property name="configLocation" value="classpath:META-INF/hibernate.cfg.xml" />
	</bean>

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

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

	<tx:annotation-driven transaction-manager="transactionManager" />

</beans> 
0

Nadal nie rozumiem po co ci jednocześnie EntityManagerFactory z JPA i SessionFactory z Hibernate.

0

To łaskawie przeczytaj komentarze pod tutorialem... Autor sam przyznaje że pisał wcześniej w Hibernate a robiąc ten tutorial chciał tam wpleść JPA, jak widać nie wyszło mu to zbyt ładnie.

0
Shalom napisał(a):

Nadal nie rozumiem po co ci jednocześnie EntityManagerFactory z JPA i SessionFactory z Hibernate.

Ponieważ potrzebuje obiektu EntityManager. Dzięki niemu wykonuje zapytania w styllu:

 List<Account> accounts= entityManager
				.createNamedQuery("Acount.getActiveByUid")
				.setParameter("uid", Long.valueOf(uid)).getResultList();

Zły sposób ?

0

Nie, ale przecież możesz za pomocą Hibernatowego Session Factory zrobić sobie obiekt Session i z niego sobie zrobić takie query. Chodzi o to że EntityManager z JPA to jest odpowiednik Session z Hibernate i korzystanie z obu jest zwyczajnie dziwne i błędogenne...

1 użytkowników online, w tym zalogowanych: 0, gości: 1