Spring-JPA-Hibernate writing to the DB fails (delaying identity-insert due to no transaction in progress)
I am using Spring 3.0.5.RELEASE and Hibernate 3.6.1.Final. Reading from the MySql DB is ok, but when I try writing to it I get this in the log:
22 mars 2011 22:37:34,625 DEBUG InjectionMetadata: Processing injected method of bean 'thoughtDao': PersistenceElement for protected javax.persistence.EntityManager com.prosveta.backend.daoimpl.GenericDaoImpl.entityManager
22 mars 2011 22:37:34,625 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'entityManagerFactory'
22 mars 2011 22:37:34,625 DEBUG DefaultListableBeanFactory: Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22 mars 2011 22:37:34,625 DEBUG DefaultListableBeanFactory: Creating instance of bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22 mars 2011 22:37:34,640 DEBUG DefaultListableBeanFactory: Eagerly caching bean 'org.springframework.transaction.config.internalTransactionAdvisor' to allow for resolving potential circular references
22 mars 2011 22:37:34,656 DEBUG DefaultListableBeanFactory: Creating shared instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0'
22 mars 2011 22:37:34,656 DEBUG DefaultListableBeanFactory: Creating instance of bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0'
22 mars 2011 22:37:34,656 DEBUG DefaultListableBeanFactory: Eagerly caching bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' to allow for resolving potential circular references
22 mars 2011 22:37:34,671 DEBUG DefaultListableBeanFactory: Finished creating instance of bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0'
22 mars 2011 22:37:34,671 DEBUG DefaultListableBeanFactory: Finished creating instance of bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22 mars 2011 22:37:34,718 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22 mars 2011 22:37:34,734 DEBUG JdkDynamicAopProxy: Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.prosveta.backend.daoimpl.thought.ThoughtDaoImpl@d337d3]
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Finished creating instance of bean 'thoughtDao'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.context.annotation.internalRequiredAnnotationProcessor'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.context.annotation.internalPersistenceAnnotationProcessor'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'prosvetaDataSource'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'entityManagerFactory'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Creating shared instance of singleton bean 'transactionManager'
22 mars 2011 22:37:34,765 DEBUG DefaultListableBeanFactory: Creating instance of bean 'transactionManager'
22 mars 2011 22:37:34,796 DEBUG DefaultListableBeanFactory: Eagerly caching bean 'transactionManager' to allow for resolving potential circular references
22 mars 2011 22:37:34,796 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'entityManagerFactory'
22 mars 2011 22:37:34,796 DEBUG DefaultListableBeanFactory: Invoking afterPropertiesSet() on bean with name 'transactionManager'
22 mars 2011 22:37:34,796 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Finished creating instance of bean 'transactionManager'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Creating shared instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Creating instance of bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Eagerly caching bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' to allow for resolving potential circular references
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Invoking afterPropertiesSet() on bean with name 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Finished creating instance of bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22 mars 2011 22:37:34,812 DEBUG DefaultListableBeanFactory: Creating shared instance of singleton bean 'thoughtDaoBean'
22 mars 2011 22:37:34,828 DEBUG DefaultListableBeanFactory: Creating instance of bean 'thoughtDaoBean'
22 mars 2011 22:37:34,828 DEBUG DefaultListableBeanFactory: Eagerly caching bean 'thoughtDaoBean' to allow for resolving potential circular references
22 mars 2011 22:37:34,828 DEBUG InjectionMetadata: Processing injected method of bean 'thoughtDaoBean': PersistenceElement for protected javax.persistence.EntityManager com.prosveta.backend.daoimpl.GenericDaoImpl.entityManager
22 mars 2011 22:37:34,828 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'entityManagerFactory'
22 mars 2011 22:37:34,828 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22 mars 2011 22:37:34,828 DEBUG JdkDynamicAopProxy: Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.prosveta.backend.daoimpl.thought.ThoughtDaoImpl@1f2af1c]
22 mars 2011 22:37:34,828 DEBUG DefaultListableBeanFactory: Finished creating instance of bean 'thoughtDaoBean'
22 mars 2011 22:37:34,828 DEBUG ClassPathXmlApplicationContext: Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@a36b53]
22 mars 2011 22:37:34,828 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'lifecycleProcessor'
22 mars 2011 22:37:34,828 DEBUG DefaultListableBeanFactory: Returning cached instance of singleton bean 'thoughtDaoBean'
22 mars 2011 22:37:34,859 DEBUG SharedEntityManagerCreator$SharedEntityManagerInvocationHandler: Creating new EntityManager for shared EntityManager invocation
22 mars 2011 22:37:34,968 DEBUG SessionImpl : opened session at timestamp: 5328199085629440
22 mars 2011 22:37:35,031 DEBUG AbstractSaveEventListener: delaying identity-insert due to no transaction in progress
22 mars 2011 22:37:35,031 DEBUG EntityManagerFactoryUtils: Closing JPA EntityManager
with AbstractSaveEventListener: delaying identity-insert due to no transaction in progress one line before end.
I've been searching for long hours, comparing my Spring config files with others on the net, but without result.
Here are the config files:
mysql connector
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.15</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
persistence.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="prosvetaPersistenceUnit"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.prosveta.backend.model.thought.Thought</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<!--
value='create' to build a new database on each run;
value='update' to modify an existing database;
value='create-drop' means the same as 'create' but also drops tables when Hibernate closes;
value='validate' makes no changes to the database
-->
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>
<!--
<property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider"/>
<property name="hibernate.search.default.indexBase" value="./lucene/indexes"/>
<property name="hibernate.search.default.batch.merge_factor" value="10"/>
<property name="hibernate.search.default.batch.max_buffered_docs" value="10"/>
-->
</properties>
</persistence-unit>
</persistence>
spring-jpa.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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">
<!-- JPA Entity Manager Factory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="prosvetaDataSource">
<property name="persistenceUnitName" value="prosvetaPersistenceUnit" />
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Database LOB Handling -->
<!-- bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" / -->
<!-- Read in DAOs from the JPA package -->
<context:component-scan base-package="com.prosveta.backend.daoimpl" />
<!-- Transaction Config -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" />
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />
</beans>
datasource.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- Basic DataSource -->
<bean id="prosvetaDataSource"
class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
</beans>
jdbc.properties
# Properties file with JDBC-related settings applied by PropertyPlaceholderConfigurer.
jdbc.url=jdbc:mysql://localhost/p_joo15_dev?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=pw
spring-master-dao-test.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
<context:component-scan base-package="com.prosveta.backend">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
<!-- This will ensure that hibernate or jpa exceptions are automatically translated into
Spring's generic DataAccessException hierarchy -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<import resource="spring-datasource.xml"/>
<import resource="spring-jpa.xml"/>
<!-- required only for main method in ThoughtDaoImpl used to investigate
the delayed db creation problem -->
<bean id="thoughtDaoBean" class="com.prosveta.backend.daoimpl.thought.ThoughtDaoImpl" />
</beans>
and now the java code
the model class
package com.prosveta.backend.model.thought;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.QueryHint;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persiste开发者_StackOverflownce.Transient;
import com.prosveta.backend.model.DomainObject;
import com.prosveta.backend.model.language.Language;
@SuppressWarnings("serial")
@Entity
@Table(name="jos_thoughts_p")
@NamedQueries({
@NamedQuery(name = "Thought.getThought",
query = "select thought from Thought thought where thought.date = :date and thought.language = :language",
hints={@QueryHint(name="org.hibernate.cacheable",value="true")}),
@NamedQuery(name = "Thought.getAllThoughtIdsBeforeDate",
query = "select thought.id from Thought thought where thought.date < :date and thought.language = :language",
hints={@QueryHint(name="org.hibernate.cacheable",value="true")}),
// it seems not a good idea to cache the query below since the 2 dates doublet has few chances to be used often in a short period of time !
@NamedQuery(name = "Thought.getAllThoughtIdsBeforeDateExceptExclusionDate",
query = "select thought.id from Thought thought where thought.date < :date and thought.language = :language and thought.date != :exclusionDate"),
})
public class Thought implements DomainObject {
private Integer id;
private Date date;
private String language;
private Integer treeOfLife;
private Integer twoNatures;
private String text;
private String keyword;
private String sentence;
public Thought() {
}
public Thought(Integer id, Date date, String language, Integer treeOfLife,
Integer twoNatures, String text, String keyword, String sentence) {
super();
this.id = id;
this.date = date;
this.language = language;
this.treeOfLife = treeOfLife;
this.twoNatures = twoNatures;
this.text = text;
this.keyword = keyword;
this.sentence = sentence;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Temporal(TemporalType.DATE)
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
/**
* Returns the Language enum denoting the thought language
* @return
*/
@Transient
public Language getLanguageEnum() {
return Language.valueOf(language);
}
@Column(name = "tree_of_life", columnDefinition="SMALLINT")
public Integer getTreeOfLife() {
return treeOfLife;
}
public void setTreeOfLife(Integer treeOfLife) {
this.treeOfLife = treeOfLife;
}
@Column(name = "2_natures", columnDefinition="SMALLINT")
public Integer getTwoNatures() {
return twoNatures;
}
public void setTwoNatures(Integer twoNatures) {
this.twoNatures = twoNatures;
}
@Column(columnDefinition="LONGTEXT")
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getSentence() {
return sentence;
}
public void setSentence(String sentence) {
this.sentence = sentence;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Thought [id=" + id + ", date=" + date + ", language="
+ language + ", treeOfLife=" + treeOfLife + ", twoNatures="
+ twoNatures + ", text=" + text + ", keyword=" + keyword
+ ", sentence=" + sentence + "]";
}
}
the generic dao base class
package com.prosveta.backend.daoimpl;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.dao.DataAccessException;
import com.prosveta.backend.dao.GenericDao;
import com.prosveta.backend.model.DomainObject;
/*
* This class contains a generic JPA implementation of
* the CRUD operations provided by dao's.
*/
@SuppressWarnings("unchecked")
public class GenericDaoImpl<T extends DomainObject> implements GenericDao<T> {
private Class<T> type;
@PersistenceContext
protected EntityManager entityManager;
public GenericDaoImpl(Class<T> type) {
super();
this.type = type;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public EntityManager getEntityManager() {
return this.entityManager;
}
public T get(Long id) {
return (T) this.entityManager.find(type, id);
}
public List<T> getAll() {
return this.entityManager.createQuery(
"select obj from " + type.getName() + " obj").getResultList();
}
public void save(T object) throws DataAccessException {
this.entityManager.persist(object);
}
public void delete(T object) throws DataAccessException {
this.entityManager.remove(object);
}
}
the dao class with the main method I am using to trace the persistence problem
package com.prosveta.backend.daoimpl.thought;
import java.util.Date;
import java.util.List;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.prosveta.backend.dao.thought.ThoughtDao;
import com.prosveta.backend.daoimpl.GenericDaoImpl;
import com.prosveta.backend.model.language.Language;
import com.prosveta.backend.model.thought.Thought;
@Repository("thoughtDao")
public class ThoughtDaoImpl extends GenericDaoImpl<Thought> implements
ThoughtDao {
private static Log log = LogFactory.getLog(ThoughtDaoImpl.class);
private ThoughtDaoImpl() {
super(Thought.class);
}
/*
* (non-Javadoc)
*
* @see
* com.prosveta.backend.dao.thought.ThoughtDao#getThought(java.util.Date,
* com.prosveta.backend.model.language.Language)
*/
public Thought getThought(Date date, Language language) {
Query q = this.entityManager.createNamedQuery("Thought.getThought");
q.setParameter("date", date);
q.setParameter("language", language.toString());
Thought thought = null;
try {
thought = (Thought) q.getSingleResult();
} catch (NoResultException e) {
log.error("No thought found for date " + date + " and language "
+ language);
throw e;
}
log.debug("Thought retrieved from db: " + thought);
return thought;
}
/*
* (non-Javadoc)
*
* @see com.prosveta.backend.dao.thought.ThoughtDao#
* getAllThoughtIdsForThoughtBeforeDate(java.util.Date,
* com.prosveta.backend.model.language.Language)
*/
@SuppressWarnings("unchecked")
@Override
public List<Long> getAllThoughtIdsForThoughtBeforeDate(Date date,
Language language) {
Query q = this.entityManager
.createNamedQuery("Thought.getAllThoughtIdsBeforeDate");
q.setParameter("date", date);
q.setParameter("language", language.toString());
List<Long> ids = q.getResultList();
log.debug(ids.size()
+ " thought ids retrieved from db satisfying date < " + date
+ " for language " + language);
return ids;
}
/*
* (non-Javadoc)
*
* @see com.prosveta.backend.dao.thought.ThoughtDao#
* getAllThoughtIdsForThoughtBeforeDateExceptExclusionDate(java.util.Date,
* com.prosveta.backend.model.language.Language, java.util.Date)
*/
@SuppressWarnings("unchecked")
@Override
public List<Long> getAllThoughtIdsForThoughtBeforeDateExceptExclusionDate(
Date date, Language language, Date exclusionDate) {
Query q = this.entityManager
.createNamedQuery("Thought.getAllThoughtIdsBeforeDateExceptExclusionDate");
q.setParameter("date", date);
q.setParameter("language", language.toString());
q.setParameter("exclusionDate", exclusionDate);
List<Long> ids = q.getResultList();
log.debug(ids.size()
+ " thought ids retrieved from db satisfying date < " + date
+ " and != " + exclusionDate + " for language " + language);
return ids;
}
public static void main(String[] args) {
ThoughtDao thoughtDao = null;
try {
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "classpath:/META-INF/spring/spring-master-dao-test.xml" });
thoughtDao = (ThoughtDao) context.getBean("thoughtDaoBean");
} catch (Exception e) {
log.fatal(e);
throw new RuntimeException(e);
}
Thought thought = new Thought(null, new Date(),
"FR", new Integer(0), new Integer(0),
"Pensée 1", "", "");
saveThought(thoughtDao, thought);
}
/**
* @param thoughtDao
* @param t1
*/
@Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW)
private static void saveThought(ThoughtDao thoughtDao, Thought t1) {
thoughtDao.save(t1);
}
}
Thanks a lot for your help and thanks for reading !
Jean-Pierre
Spring can wrap a method into a transaction if it's an instance method of a bean it has instantiated. You put the @Transactional
annotation on a static method directly called from the main method. Spring can't wrap this call into a transaction. Put the annotation on the save method, and it should work better.
精彩评论