Spring-JPA-Hibernate写入数据库失败(由于没有正在进行的事务而延迟身份插入)

时间:2011-03-22 22:10:31

标签: mysql hibernate spring jpa-2.0

我正在使用Spring 3.0.5.RELEASE和Hibernate 3.6.1.Final。从MySql DB读取是可以的,但是当我尝试写入它时,我在日志中得到了这个:

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

使用 AbstractSaveEventListener:由于没有正在进行的事务而延迟身份插入在结束前一行。

我一直在寻找很长时间,将我的Spring配置文件与网上的其他人进行比较,但没有结果。

以下是配置文件:

mysql连接器

<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>

弹簧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

弹簧主-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>

现在是java代码

模型类

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.persistence.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 + "]";
    }
}

通用dao基类

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);
    }
}

使用我用来跟踪持久性问题的主要方法的dao类

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);
    }
}

非常感谢您的帮助,感谢您的阅读!

让 - 皮埃尔

1 个答案:

答案 0 :(得分:6)

Spring可以将方法包装到事务中,如果它是已实例化的bean的实例方法。您将@Transactional注释放在从main方法直接调用的静态方法上。 Spring无法将此调用包装到事务中。将注释放在save方法上,它应该更好。