- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我将 Spring 与 JPA 一起使用。我打开了 @EnableAsync
和 @EnableTransactionManagement
。在我的用户注册服务方法中,我调用了一些其他的服务方法,它们被注释为 @Async
。这些方法可以做各种各样的事情,比如发送欢迎电子邮件和向我们的第三方支付系统注册新用户。
在我想验证第三方支付系统是否成功创建用户之前,一切正常。此时,@Async
方法会尝试创建一个 UserAccount
(它引用新生成的 User
)并使用 出错javax.persistence.EntityNotFoundException:无法找到 com.dk.st.model.User 的 id 为 2017
注册调用如下所示:
private User registerUser(User newUser, Boolean waitForAccount) {
String username = newUser.getUsername();
String email = newUser.getEmail();
// ... Verify the user doesn't already exist
// I have tried all manner of flushing and committing right here, nothing works
newUser = userDAO.merge(newUser);
// Here is where we register the new user with the payment system.
// The User we just merged is not /actually/ in the DB
Future<Customer> newCustomer = paymentService.initializeForNewUser(newUser);
// Here is where I occasionally (in test methods) pause this thread to wait
// for the successful account creation.
if (waitForAccount) {
try {
newCustomer.get();
} catch (Exception e) {
logger.error("Exception while creating user account!", e);
}
}
// Do some other things that may or may not be @Aysnc
return newUser;
}
支付服务调用它来完成注册用户的工作,如下所示:
@Async
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Future<Customer> initializeForNewUser(User newUser) {
// ... Set up customerParams
Customer newCustomer = null;
try {
newCustomer = Customer.create(customerParams);
UserAccount newAccount = new UserAccount();
newAccount.setUser(newUser);
newAccount.setCustomerId(newCustomer.getId());
newAccount.setStatus(AccountStatus.PRE_TRIAL);
// When merging, JPA cannot find the newUser object in the DB and complains
userAccountDAO.merge(newAccount);
} catch (Exception e) {
logger.error("Error while creating UserAccount!", e);
throw e;
}
return new AsyncResult<Customer>(newCustomer);
}
列出的 StackOverflow 答案 here建议我设置一个 REQUIRES_NEW
传播,我已经这样做了,但没有这样的运气。
谁能指出我正确的方向?我真的不想直接从我的 Controller 方法调用 paymentService 。我觉得这肯定是服务级别的调用。
感谢您的帮助!
最佳答案
在 Vyncent 的帮助下,这是我得出的解决方案。我创建了一个名为 UserCreationService
的新类,并将处理 User
创建的所有方法都放在该类中。这是一个例子:
@Override
public User registerUserWithProfileData(User newUser, String password, Boolean waitForAccount) {
newUser.setPassword(password);
newUser.encodePassword();
newUser.setJoinDate(Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime());
User registered = userService.createUser(newUser);
registered = userService.processNewRegistration(registered, waitForAccount);
return userService.setProfileInformation(registered);
}
您会注意到此方法上有 NO @Transactional
注释。这是故意的。对应的 createUser
和 processNewRegistration
定义如下所示:
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public User createUser(User newUser) {
String username = newUser.getUsername();
String email = newUser.getEmail();
if ((username != null) && (userDAO.getUserByUsername(username) != null)) {
throw new EntityAlreadyExistsException("User already registered: " + username);
}
if (userDAO.getUserByUsername(newUser.getEmail()) != null) {
throw new EntityAlreadyExistsException("User already registered: " + email);
}
return userDAO.merge(newUser);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public User processNewRegistration(
User newUser,
Boolean waitForAccount)
{
Future<UserAccount> customer = paymentService.initializeForNewUser(newUser);
if (waitForAccount) {
try {
customer.get();
} catch (Exception e) {
logger.error("Error while creating Customer object!", e);
}
}
// Do some other maintenance type things...
return newUser;
}
Vyncent 发现事务管理是问题所在。创建其他服务使我能够更好地控制这些事务何时提交。虽然我最初对采用这种方法犹豫不决,但这是与 Spring 托管事务和代理的权衡。
我希望这可以帮助其他人在以后节省一些时间。
关于java - 使用@Async 嵌套@Transactional 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29258436/
我不明白注释之间的实际区别是什么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 个回答)
我是一名优秀的程序员,十分优秀!