EclipseLink with Spring - Can't persist into Db
I am using Spring + EclipseLink 2 to manage entity on a Derby database. Select object from db works fine but when I try to persist one, nothing happens. Program executes correctly and no exception are thrown. I probably did something wrong, as I'm not familiar with Spring, thanks for your comments and suggestions :)
The ServerDaoDb method :
@Transactional
public void addServer(Server server) {
EntityManager em = emf.createEntityManager();
emf.createEntityManager().persist(server);
em.close();
}
Application context is :
...
<tx:annotation-driven />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="SpringPratiquePU" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
Persistence.xml :
<persistence-unit name="SpringPratiquePU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>net.athom.spring.examples.models.eas.Server</class>
<class>net.athom.spring.examples.models.eas.Node</class>
<properties>
<property name="eclipselink.target-database" value=开发者_如何学编程"DERBY"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/SpringPratique"/>
<property name="javax.persistence.jdbc.password" value="clem"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.user" value="clem"/>
</properties>
</persistence-unit>
</persistence>
The Debug Trace :
DEBUG JpaTransactionManager:365 - Creating new transaction with name [net.athom.spring.examples.service.impl.ServerManagerImpl.addServer]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
[EL Info]: 2010-10-29 15:33:27.443--ServerSession(14894886)--EclipseLink, version: Eclipse Persistence Services - 2.0.2.v20100323-r6872
[EL Info]: 2010-10-29 15:33:28.606--ServerSession(14894886)--file:/C:/netbeanProject/SpringPratique/src/_SpringPratiquePU login successful
15:33:28,893 DEBUG JpaTransactionManager:323 - Opened new EntityManager [org.eclipse.persistence.internal.jpa.EntityManagerImpl@1779885] for JPA transaction
15:33:28,951 DEBUG DefaultListableBeanFactory:242 - Returning cached instance of singleton bean 'transactionManager'
15:33:28,952 DEBUG JpaTransactionManager:286 - Found thread-bound EntityManager [org.eclipse.persistence.internal.jpa.EntityManagerImpl@1779885] for JPA transaction
15:33:28,953 DEBUG JpaTransactionManager:470 - Participating in existing transaction
15:33:29,266 DEBUG JpaTransactionManager:752 - Initiating transaction commit
15:33:29,267 DEBUG JpaTransactionManager:462 - Committing JPA transaction on EntityManager [org.eclipse.persistence.internal.jpa.EntityManagerImpl@1779885]
15:33:29,268 DEBUG JpaTransactionManager:548 - Closing JPA EntityManager [org.eclipse.persistence.internal.jpa.EntityManagerImpl@1779885] after transaction
15:33:29,308 DEBUG EntityManagerFactoryUtils:328 - Closing JPA EntityManager
Your error is here:
@Transactional
public void addServer(Server server) {
EntityManager em = emf.createEntityManager();
emf.createEntityManager().persist(server);
em.close();
}
Your are creating two different EntityManager instances, the em
, which you are closing, and a new one at the next line with emf.createEntityManager()
which you are using directly to persist your changes.
Try this:
@Transactional
public void addServer(Server server) {
EntityManager em = emf.createEntityManager();
em.persist(server);
em.close();
}
I guess that when you close your em instance, your changes are written to the DB, but, in case that they are not, you have to add em.flush();
right before closing the em
instance.
I am not sure what exactly is wrong with your configuration (I guess EntityManager
created manually can't participate in @Transactional
transactions), but the typical JPA configuration in Spring looks like this, so you don't need to create EntityManager
manually (also note the classname of the factory bean):
@PersistenceContext
private EntityManager em;
@Transactional
public void addServer(Server server) {
em.persist(server);
}
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="SpringPratiquePU" />
</bean>
Thx for your answers, both were very helpful. I ended up using LocalContainerEntityManagerFactoryBean, so I could inject the entity manager into my dao. I added servlet-agent-2.5.6.jar on the lib folder and and pass VM options : -javaagent:path/to/lib/ervlet-agent-2.5.6.jar
Then I modified ApplicationContext.xml :
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="SpringPratiquePU" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
And my dao: ...
@PersistenceContext
private EntityManager em;
@Transactional
public void addServer(Server server) {
em.persist(server);
}
Persistence and transactions work like a charm now !
精彩评论