2016-09-08 2 views
1

J'ai une application de printemps qui utilise JTA (essayé à la fois atomikos et bitronix avec le même problème) + JPA (Hibernate), et je cours dans le problème suivantSynchronisation de transaction de printemps fermant le gestionnaire d'entité JPA avant la fin de la transaction lorsque la clé étrangère est présente

Tout fonctionne depuis jusqu'à ce que j'essaie d'utiliser des clés étrangères (par exemple une relation OneToOne, la cascade ne fait pas de différence).

Quand je fais, le synchroniseur de transaction ressort de force fermer le gestionnaire d'entités avant que la transaction est terminée, et lorsque le gestionnaire de transactions essaie de commettre puis-je obtenir simplement:

ERROR: HHH000346: Error during managed flush [Session/EntityManager is closed] 

Il n'y a pas d'autres journaux qui indiquer pourquoi le printemps ferme le gestionnaire d'entité au début.

J'ai découvert que si je fais un entitymenager.flush(), cela résout dans le problème dans la plupart des cas, mais pas tous.

J'ai un projet avec des tests unitaires qui répliquent le problème: https://github.com/Kloudtek/ktspring (les tests unitaires sont ceux pour autonomes/atomikos-artemis-mise en veille prolongée

Voici un extrait de ce que j'utilise

@Bean(initMethod = "init", destroyMethod = "shutdownForce") 
public UserTransactionServiceImp userTransactionService() { 
    Properties p = new Properties(); 
    p.setProperty("com.atomikos.icatch.service", "com.atomikos.icatch.standalone.UserTransactionServiceFactory"); 
    p.setProperty("com.atomikos.icatch.default_jta_timeout","30000"); 
    return new UserTransactionServiceImp(p); 
} 

@Bean(initMethod = "init", destroyMethod = "close") 
@DependsOn("userTransactionService") 
public UserTransactionManager UserTransactionManager() { 
    UserTransactionManager userTransactionManager = new UserTransactionManager(); 
    userTransactionManager.setForceShutdown(false); 
    userTransactionManager.setStartupTransactionService(false); 
    return userTransactionManager; 
} 

@Bean 
@DependsOn("userTransactionService") 
public UserTransactionImp userTransactionImp() throws SystemException { 
    UserTransactionImp userTransactionImp = new UserTransactionImp(); 
    return userTransactionImp; 
} 

@Bean 
@DependsOn("userTransactionService") 
public JtaTransactionManager jtaTransactionManager() { 
    return new JtaTransactionManager(UserTransactionManager(), UserTransactionManager()); 
} 

@Bean 
public JPAParams jpaParams() { 
    Properties p = new Properties(); 
    p.setProperty("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION"); 
    p.setProperty("hibernate.current_session_context_class", "jta"); 
    p.setProperty("hibernate.transaction.jta.platform", AtomikosPlatform.class.getName()); 
    return new JPAParams(p); 
} 

@Bean 
public LocalContainerEntityManagerFactoryBean entityManager() { 
    LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); 
    if (config.isJtaDatasource()) { 
     entityManager.setJtaDataSource(config.getDataSource()); 
    } else { 
     entityManager.setDataSource(config.getDataSource()); 
    } 
    Properties p = new Properties(); 
    p.putAll(config.getJpaProperties()); 
    if (jpaParamsList != null) { 
     for (JPAParams jpaParams : jpaParamsList) { 
      p.putAll(jpaParams.getProperties()); 
     } 
    } 
    entityManager.setJpaProperties(p); 
    entityManager.setPackagesToScan(config.getPackageToScan()); 
    entityManager.setPersistenceProvider(new HibernatePersistenceProvider()); 
    return entityManager; 
} 

@Entity 
public class TestObj { 
    @Id 
    private int id; 
    @OneToOne 
    private TestObj2 testObj2; 

    public TestObj() { 
    } 

    public TestObj(int id) { 
     this.id = id; 
    } 

    public TestObj(int id, TestObj2 testObj2) { 
     this.id = id; 
     this.testObj2 = testObj2; 
    } 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 
} 

@Entity 
public class TestObj2 { 
    @Id 
    private int id; 

    public TestObj2() { 
    } 

    public TestObj2(int id) { 
     this.id = id; 
    } 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 
} 

public void testDb() { 
    tx.execute(status -> { 
     entityManager.persist(new TestObj3(0)); 
     TestObj2 o2 = new TestObj2(0); 
     entityManager.persist(o2); 
     TestObj o1 = new TestObj(0, o2); 
     entityManager.persist(o1); 
     // If i flush the problem disapears 
     // entityManager.flush(); 
     return null; 
    }); 
} 

Répondre

1

Nous avons eu un problème similaire avec ressort 4.3.2 et Hibernate 5.2.2 dévalorisation mise en veille prolongée à 5.1.1 résolu notre problème

+0

il y a encore des problèmes au printemps 4.3.2 avec mise en veille prolongée ensemble 5.2.2 ex: https: //jira.spring.io/browse/SPR-14676 – Joram

+0

Fantastique qui a effectivement résolu le problème. Seriez-vous capable de savoir si ce problème spécifique est un bug en hibernation ou un bug au printemps? –

+0

Pas vraiment une solution, je pense, juste une solution de contournement. Je n'ai pas regardé dans les détails, mais Hibernate 5.2 contient quelques changements de rupture dans la préparation de 6.0 – Joram