- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到一个问题,如果我有一个客户端在我的服务上调用两个方法,则会失败,第二个方法中的事务没有与之关联的 session 。但是,如果我将这两种方法组合到服务中并从客户端代码调用该方法,那么它就会成功。
谁能向我解释一下为什么会发生这种情况?
考虑以下代码:
@Configurable
public class ParentService {
@PersistenceContext
private EntityManager entityManager;
public ParentService() {
}
@Transactional
public Parent findById( Long id ) {
return entityManager.findById( Parent.class, id );
}
@Transactional
public Set<Child> getChildrenFor( Parent parent ) {
return Collections.unmodifiableSet( new HashSet<>( parent.getChildren() ) );
}
@Transactional
public Set<Child> getChildrenFor( Long id ) {
Parent parent = findById( id );
return getChildrenFor( parent );
}
...
}
所以这里发生的情况是,在我的客户端代码(不了解事务)中,如果我调用#getChildrenFor(id),我就没事了。但如果我打电话:
Parent parent = service.findById( id );
Set<Child> children = service.getChildrenOf( parent );
然后 hibernate 抛出一个异常,表示没有与当前事务关联的 session ,因此它无法迭代 #getChildren 的延迟加载的 PersistentSet。
现在我不是 JPA 或 Spring 专家,所以也许这是有意的行为。如果是的话你能告诉我为什么吗?我是否需要创建一个不是要公开的服务的实体的 DTA,然后让我的客户使用它而不是该实体?我认为,由于两个调用都使用相同的实体管理器引用,因此客户端应该能够进行这两个调用。
顺便说一句,这是使用 CTW“ Spring 配置”。 JpaTransactionManager 配置为横切,如下所示:
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txnMgr = new JpaTransactionManager();
txnMgr.setEntityManagerFactory( entityManagerFactory().getObject() );
// cross cut transactional methods with txn management
AnnotationTransactionAspect.aspectOf().setTransactionManager( txnMgr );
return txnMgr;
}
请告诉我我可以提供的任何其他信息来帮助解决此问题。
Spring 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:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<context:spring-configured/>
<context:component-scan base-package="com.myapp"/>
</beans>
Spring Java 配置:
@Configuration
@PropertySource( "classpath:database.properties" )
public class DatabaseConfiguration {
@Value( "${database.dialect}" )
private String databaseDialect;
@Value( "${database.url}" )
private String databaseUrl;
@Value( "${database.driverClassName}" )
private String databaseDriver;
@Value( "${database.username}" )
private String databaseUser;
@Value( "${database.password}" )
private String databasePassword;
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setPersistenceUnitName( "persistenceUnit" );
factory.setDataSource( dataSource() );
Properties props = new Properties();
props.setProperty( "hibernate.dialect", databaseDialect );
factory.setJpaProperties( props );
return factory;
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txnMgr = new JpaTransactionManager();
txnMgr.setEntityManagerFactory( entityManagerFactory().getObject() );
// cross cut transactional methods with txn management
AnnotationTransactionAspect.aspectOf().setTransactionManager( txnMgr );
return txnMgr;
}
@Bean
public DataSource dataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName( databaseDriver );
dataSource.setUrl( databaseUrl );
dataSource.setUsername( databaseUser );
dataSource.setPassword( databasePassword );
dataSource.setTestOnBorrow( true );
dataSource.setTestOnReturn( true );
dataSource.setTestWhileIdle( true );
dataSource.setTimeBetweenEvictionRunsMillis( 1800000 );
dataSource.setNumTestsPerEvictionRun( 3 );
dataSource.setMinEvictableIdleTimeMillis( 1800000 );
return dataSource;
}
}
POM:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.2</version>
<!-- NB: do not use 1.3 or 1.3.x due to MASPECTJ-90 and do not use 1.4 due to de`clare parents issue -->
<dependencies>
<!-- NB: You must use Maven 2.0.9 or above or these are ignored (see MNG-2972) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
最佳答案
使用 JTA 事务时, session (即或多或少的实体管理器)会自动绑定(bind)到事务。这意味着事务 T1 期间获取的实体是在与 T1 绑定(bind)的实体管理器/ session 中获取的。
一旦提交 T1,entityManager/session 就不再附加到任何事务(因为 T1 已完成)。
当您的客户这样做时:
Parent parent = service.findById( id );
Set<Child> children = service.getChildrenFor( parent );
parent
在 T1 期间获取,因此它绑定(bind)到与 T1 绑定(bind)的 entityManager
(我们称之为 EM1)。但 T1 已完成(当 findById
返回时已提交)。
由于 getChildrenFor
带有 @Transactional
注释:txManager 启动了一个新的 tx(即 T2)。这将创建一个与 T2 关联的新实体管理器(即 EM2)。但 parent
属于 EM1,并且 EM1 仍未绑定(bind)到任何正在运行的交易。
要解决您的问题,您可以调整此方法的代码:
@Transactional
public Set<Child> getChildrenFor( Parent parent ) {
Parent mergedParent = entityManager.merge(parent);
return Collections.unmodifiableSet( new HashSet<>( mergedParent.getChildren() ) );
}
调用merge
将会
Merge the state of the given entity into the current persistence context.
(请注意,持久化上下文是与当前entityManager关联的存储)
mergedParent
现在属于 EM2,并且 EM2 绑定(bind)到当前运行的 T2,因此调用 mergedParent.getChildren()
不会失败。
关于merge
的重要说明:重要的是要注意merge
返回一个新实例并且不' t 触摸参数中传递的实例。在使用 JPA 时,认为合并
修改实例是一个非常常见的错误/误解。
此时,我希望您明白,当您在同一个 tx 中获取父级和子级(调用 getChildrenFor( Long id )
)时,无需合并,因为(父级和子级) Children) 属于同一个entityManager。
关于java - 多个JTA事务: no session associated with the current transaction,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14591287/
我不明白注释之间的实际区别是什么javax.transaction.Transactional和org.springframework.transaction.annotation.Transacti
我不明白注释 javax.transaction.Transactional 和 org.springframework.transaction.annotation.Transactional 之间
我正在尝试删除一个节点。 我知道要先删除节点,我必须删除关系。 MATCH (n:`Dummy`) WHERE n.uuid='1aa41234-aaaa-xxxx-ffff-xxxx11xx0x62
假设我有一个共享钱包,可以为我和我的兄弟收集以太币。我们彼此分享这个钱包的 50%。 如果有一笔 ETH 交易进入这个钱包,是否有一种自动方式可以将收到的以太币自动发送到我的个人钱包和我兄弟的钱包,而
我已经阅读并重新阅读了文档 re: mnesia:activity/3、mnesia:activity/4 和 mnesia/transaction/2,但它们对我来说仍然像是一种晦涩难懂的外语。 在
精简版: 在 Firebase 事务(在 Java 中)中,如果我从 MutableData.getValue() 中得到意外的或不一致的(陈旧的)值,我应该如何进行错误检查并确保事务在必要时重复运行
使用 Spring 时@Transcational在服务层,我需要放置 在 xml 文件上。 我想知道 可以javax.jdo.annotations.Transactional像spring一样用在
这是我的情况。 我正在构建一个 RESTful Web 服务,从客户端接收数据,然后根据该数据创建一个事件,然后我想将这个新事件推送到 celery 以异步处理它。 我使用 Pyramid 构建 RE
这是我的情况。 我正在构建一个 RESTful web 服务,它从客户端接收数据,然后从该数据创建一个事件,然后我想将这个新事件推送到 celery 以异步处理它。 我使用 pyramid 构建 RE
当我启动 jetty 时,以下行出现在日志中: :INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp
@Transactional(rollbackFor = someException.class) public void methodA() throws someException { t
我花了几个小时试图解决这个问题。谷歌和 Stackoverflow 也没有多大帮助。所以这里非常欢迎任何建议。 我正在尝试在更新两个相关表时对事务应用回滚逻辑: 一般的代码是: // ... $em
我在 Service 类中看到了一个方法,它被标记为 @Transactional,但它还在同一个类中调用了一些其他方法,这些方法没有被标记为 @Transactional。 这是否意味着对单独方法的
我目前正在使用 Microsoft Enterprise Library 5.0,我想知道下面的代码是否是处理事务的可接受方式。 我已经稍微简化了场景,但本质是我想在同一个事务中在不同的数据库中执行多
我已将以下服务方法注释为事务性: /* (non-Javadoc) * @see a.b.service.CustomerService#activateCustomer(a.b.m
以下是我的代码的一个代表性片段,其中在 transaction.Rollback() 处抛出了一个意外的异常,至少对我而言是这样。声明。 异常(exception)是类型 NHibernate.Tra
我试过将 COMMIT TRAN 放在 if else 循环中,但我仍然收到此错误。 我必须为一个类(class)招收一名学生。如果注册后的座位数为负数,我必须将其反转并打印一条消息说不能注册。我已经
我已经实现了一个具有事务的路由。当用户通过单击“后退”按钮移出这条路线时,我希望用户能够确认退出并丢失通过回滚事务所做的任何更改。 问题是,如果用户返回路由,Ember Data 会引发错误并指出:
当我从另一个事务方法调用一个事务方法时会发生什么,现在我的第二个事务方法已完成,并且它返回到第一个事务方法,不幸的是它失败了,所以它会回滚所有内容,意味着它会回滚第二个事务方法吗?交易方式改变..??
这个问题在这里已经有了答案: @Transactional method called from another method doesn't obtain a transaction (4 个回答)
我是一名优秀的程序员,十分优秀!