Spring Транзакции не работают правильно (Hibernate, JPA, Spring), почему я должен выполнить joinTransaction непосредственно перед сохранением для его работы? - PullRequest
0 голосов
/ 15 октября 2018

Я опишу следующую конфигурацию, которая по большей части работает.Я могу запросить результаты без проблем, и я могу даже выполнить персистентность с оговоркой, которую я должен выдать: entityManager.joinTransaction(); Если я этого не сделаю, мое приложение просто не выполнит персистентность и сделает это даже без жалобы!

Мои методы помечены @Transactional.Если я пытаюсь выполнить сброс сразу после сохранения, то получаю: javax.persistence.TransactionRequiredException: no transaction is in progress

Мой вопрос очень похож на этот: Метод EntityManager persist () не вставляет запись в базу данных

Сходства включают в себя:

  • Часть конфигурации получена из файла persistence.xml (это не чисто весенняя конфигурация)
  • База данных назначения - postgres(если по какой-то причине это имеет значение)
  • В последнем комментарии под принятым ответом для на этот вопрос Мишеля Юнга говорится, что ему нужно было выполнить 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();
}

Configuration:

<?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 до выполнения persist?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...