Spring事务无法正常工作(Hibernate,JPA,Spring),为什么我必须在持久化之前立即发出joinTransaction才能使其正常工作?

时间:2018-10-15 16:02:31

标签: spring hibernate jpa

我将概述以下配置,该配置在大多数情况下都有效。我可以查询结果而不会出现问题,但是我什至可以执行持久化,但是必须发出以下警告:entityManager.joinTransaction();如果我不这样做,那么我的应用程序将根本不会执行持久化,而且甚至没有抱怨!

我的方法用@Transactional注释。如果我尝试在持久存储后立即执行刷新操作,则会得到:javax.persistence.TransactionRequiredException: no transaction is in progress

我的问题与以下问题非常相似:EntityManager persist() method does not insert record to database

相似之处包括:

  • 部分配置来自persistence.xml文件(它不是纯Spring配置)
  • 目标数据库是postgres(出于某种原因应该很重要)
  • Michel Jung在that question接受的答案下的最后一条评论指出,他需要执行joinTransaction(并且由于此实现,该应用程序可以在每个持久的位置都可以使用这个愚蠢的疣工作)。对于此评论,我将有一个与此问题完全相同的问题(这是我找到它的方式),但是现在想弄清楚为什么@Transactional没有皱纹就无法工作。

一个区别是我使用的是命名持久性上下文:

@PersistenceContext(unitName = "dest")
private EntityManager emDest;
@PersistenceContext(unitName = "source")
private EntityManager emSource;

@Transactional("dest")
public void saveThing(Thing thing);
    this.emDest.joinTransaction();//without this there is no error, but it won't save
    this.emDest.persist(thing);
}

//I can itterate over the value returned from this query without issue
@Transactional("source")
public List<Thing> getThings() {
    return this.emSource.createNamedQuery(
            "Thing.findAll", Thing.class)
            .getResultList();
}

配置:

<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="dest" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.quaternion.destination.OtherThing</class>
        <-- lot of other entity classes created by the IDE/Hibernates JPA Model Gen-->
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/dest"/>
            <property name="javax.persistence.jdbc.user" value="a_user"/>
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
            <property name="javax.persistence.jdbc.password" value="password"/>
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
            <property name="javax.persistence.schema-generation.database.action" value="none"/>
            <property name="spring.jpa.database-platform" value="org.hibernate.dialect.PostgreSQLDialect"/>
            <property name = "hibernate.show_sql" value = "true" />
        </properties>
    </persistence-unit>
    <persistence-unit name="source" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.quaternion.source.Thing</class>
        <-- lot of other entity classes created by the IDE/Hibernates JPA Model Gen-->
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/source"/>
            <property name="javax.persistence.jdbc.user" value="a_user"/>
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
            <property name="javax.persistence.jdbc.password" value="password"/>
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
            <property name="javax.persistence.schema-generation.database.action" value="none"/>
            <property name="spring.jpa.database-platform" value="org.hibernate.dialect.PostgreSQLDialect"/>
            <property name = "hibernate.show_sql" value = "true" />
        </properties>
    </persistence-unit> </persistence>

JpaConfig.java

package ca.athabascau.gitp.hibernate.config;

import javax.persistence.EntityManagerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;

@Configuration
@EnableTransactionManagement
public class JpaConfig {

    @Bean(name = "sourceEmf")
    @Primary
    public LocalEntityManagerFactoryBean sourceEntityManagerFactory() {
        LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
        emfb.setPersistenceUnitName("source");
        return emfb;
    }

    @Bean(name = "destEmf")
    @Primary
    public LocalEntityManagerFactoryBean destEntityManagerFactory() {
        LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
        emfb.setPersistenceUnitName("dest");
        return emfb;
    }

    @Bean(name = "dest")
    public JpaTransactionManager destinationTransactionManager() {
        JpaTransactionManager jpaTransactionManager = new org.springframework.orm.jpa.JpaTransactionManager();
        EntityManagerFactory emf = this.destEntityManagerFactory().getNativeEntityManagerFactory();
        jpaTransactionManager.setEntityManagerFactory(emf);
        return jpaTransactionManager;
    }

    @Bean(name = "source")
    public JpaTransactionManager sourceTransactionManager() {
        JpaTransactionManager jpaTransactionManager = new org.springframework.orm.jpa.JpaTransactionManager();
        EntityManagerFactory emf = this.sourceEntityManagerFactory().getNativeEntityManagerFactory();
        jpaTransactionManager.setEntityManagerFactory(emf);
        return jpaTransactionManager;
    }

    @Bean
    public PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
        return new PersistenceAnnotationBeanPostProcessor();
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }
}

有人对改进此设置有任何建议,可以解决我在执行持久性操作之前执行joinTransaction的需求吗?

0 个答案:

没有答案