Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么JpaRepositories似乎使用另一个事务?_Java_Spring_Hibernate_Jpa_Spring Data Jpa - Fatal编程技术网

Java 为什么JpaRepositories似乎使用另一个事务?

Java 为什么JpaRepositories似乎使用另一个事务?,java,spring,hibernate,jpa,spring-data-jpa,Java,Spring,Hibernate,Jpa,Spring Data Jpa,我有一个典型的SpringBoot(2.2.5.RELEASE)+Hibernate应用程序。尝试保存实体时,我遇到以下异常: Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: org.myorg.ConfigurationInfoEntry at org.hibernate.event.internal.DefaultPersistEventListener.onPers

我有一个典型的SpringBoot(2.2.5.RELEASE)+Hibernate应用程序。尝试保存实体时,我遇到以下异常:

Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: org.myorg.ConfigurationInfoEntry
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:828)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:795)
at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:490)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:415)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:216)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:149)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:428)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:266)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:196)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:139)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:804)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314)
at com.sun.proxy.$Proxy185.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:554)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush(SimpleJpaRepository.java:569)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:371)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:204)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:657)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:621)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 95 common frames omitted
尝试保存是通过以下方法完成的(
configurationEntryRepository
是一个JPA存储库):

ConfigurationEntry
configurationinfo条目有多对一关系:

@Entity
public final class ConfigurationEntry {
    @JoinColumn(name = "INFO_ENTRY")
    @ManyToOne(cascade = CascadeType.ALL)
    private ConfigurationInfoEntry infoEntry;
}
假设我在不了解实体分离的原因之前从数据库中获取InfoEntry。如您所见,所有内容都应该在一个事务中运行,因为方法
saveConfiguration
被适当地注释了

但是,当我将ConfigurationEntry更改为cascade而不保留时,即更改为:

@Entity
public final class ConfigurationEntry {
    @JoinColumn(name = "INFO_ENTRY")
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REMOVE, CascadeType.DETACH, CascadeType.REFRESH } )
    private ConfigurationInfoEntry infoEntry;
}
一切正常。这让我相信JpaRepository在read调用和saveAndFlush()操作之间使用了两种不同的事务,从而导致在读取后分离实体。然而,考虑到整个方法都使用事务性注释,我真的不明白为什么

以下是我的数据源和JPA相关bean的配置:

@Bean(value = "datasource")
public DataSourceFactoryBeanHikari dataSourceFactoryBeanHikari() {
    DataSourceFactoryBeanHikari dataSourceFactoryBeanHikari = new DataSourceFactoryBeanHikari();
    dataSourceFactoryBeanHikari.setMaxPoolSize(30);
    return dataSourceFactoryBeanHikari;
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory);
    return txManager;
}

@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
    return new JdbcTemplate(dataSource);
}

@Bean("entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    em.setPackagesToScan("org.myorg");

    final Map<String, Object> properties = new HashMap<>();
    properties.put(AvailableSettings.DIALECT, "org.hibernate.dialect.SQLServerDialect");
    properties.put(AvailableSettings.URL, "jdbc:sqlserver://localhost:1433");
    properties.put(AvailableSettings.SHOW_SQL, true);
    properties.put(AvailableSettings.FORMAT_SQL, true);
    properties.put(AvailableSettings.HBM2DDL_AUTO, "none");
    em.setJpaPropertyMap(properties);
    em.setDataSource(dataSource);
    em.afterPropertiesSet();

    return em;
}
@Bean(value=“datasource”)
公共数据源FactoryBeanhikari数据源FactoryBeanhikari(){
DataSourceFactoryBeanHikari DataSourceFactoryBeanHikari=新数据源FactoryBeanhikari();
dataSourceFactoryBeanHikari.setMaxPoolSize(30);
返回数据源FactoryBeanhikari;
}
@豆子
公共平台transactionManager transactionManager(EntityManager工厂EntityManager工厂){
JpaTransactionManager txManager=新的JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
返回txManager;
}
@豆子
公共JdbcTemplate JdbcTemplate(数据源数据源){
返回新的JdbcTemplate(数据源);
}
@Bean(“EntityManager工厂”)
公共LocalContainerEntityManagerFactoryBean entityManagerFactory(数据源数据源){
最终LocalContainerEntityManagerFactoryBean em=新的LocalContainerEntityManagerFactoryBean();
em.setJpaVendorAdapter(新的hibernatejpavendorapter());
em.setPackagesToScan(“org.myorg”);
最终映射属性=新HashMap();
properties.put(AvailableSettings.dialogue,“org.hibernate.dialogue.sqlserverdialogue”);
properties.put(AvailableSettings.URL,“jdbc:sqlserver://localhost:1433");
properties.put(AvailableSettings.SHOW_SQL,true);
properties.put(AvailableSettings.FORMAT_SQL,true);
properties.put(AvailableSettings.HBM2DDL_AUTO,“无”);
em.setJpaPropertyMap(属性);
em.setDataSource(数据源);
em.afterPropertiesSet();
返回em;
}

线程中的讨论摘要:

检查是否存在活动的方面管理事务

System.out.println(
  TransactionAspectSupport.currentTransactionStatus()
);
结果是没有。 上面的代码抛出了

NoTransactionException: No transaction aspect-managed TransactionStatus in scope
检查未遵守@Transactional的原因

由于
@EnableTransactionManagement
是由Spring Boot自动配置的,下一个可能是Spring AOP代理的使用不正确

SpringAOP包装对象,从同一实例调用时不会截获这些方法

事实确实如此


请参见

这是单向关系还是双向关系?@Lesiak uni-directive,即ConfigurationInfo条目没有对ConfigurationEntry的引用检查您是否在范围内有事务方面管理的TransactionStatus:`System.out.println(TransactionSpectSupport.currentTransactionStatus());`。如果没有活动事务,它将抛出异常。是否启用了基于批注的事务管理?@Lesiak否,没有活动事务(抛出NotTransactionException:范围内没有事务方面管理的TransactionStatus)。但是基于注释的事务管理应该启用,首先是因为这应该是Spring引导的默认值,而且当我在我的ApplicationInded中使用“@EnableTransactionManagement”启用它时,它是自动配置的。您是否有可能从同一类中的其他方法调用此方法?
NoTransactionException: No transaction aspect-managed TransactionStatus in scope