资讯专栏INFORMATION COLUMN

用Lambda武装你的Java: 灵活的事务

The question / 1755人阅读

摘要:假如你写了类似这样的和伪代码问题来了,和分别用了两个分开的事务,如果你用了或,并且是的,这就没法运行。你需要让两次调用运行在同一个事务里。

当你采用Spring之类的框架,用了声明式事务,难道每一段需要事务的代码都必须写成一个bean method,再标上@Transactional?

未免太麻烦了,不信你瞧。假如你写了类似这样的Controller和Service (伪代码):

class UserController {
  @Autowired UserService us;

  String updateUser(long userId) {
    User user = us.authorize(userId);
    Event e = us.update(user);
    publishToMQ(e);
    return "user-page";
  }
}

@Transactional
class UserService {
  User authorize(long userId) {...}
  void update(User user) {...}
}

问题来了,authorize和update分别用了两个分开的事务,如果你用了Hibernate或JPA,并且user是lazy-loading的,这就没法运行。你需要让两次调用运行在同一个事务里。通常的办法是把UserController.updateUser也标成@Transactional。可是这么一来,下一句publishToMQ(e);虽然不需要事务,却也被包在事务里了。

我们可以做得更好!用Java 8做一个Transactor,任何代码块可随时包在事务中!
然后controller可以重写为:

String updateUser(long userId) {
  Event e = Transactor.get().apply(() -> {
    User user = us.authorize(userId);
    return us.update(user);
  });
  publishToMQ(e);
  return "user-page";
}

Transactor的实现:

@Component
@Transactional
public class Transactor {
  public static Transactor get() {
    return instance;
  }

  public  R apply(Supplier f) {
    return f.get(); // 有返回值的代码块
  }

  public void run(Runnable f) {
    f.run(); // 无返回值的代码块
  }

  @Autowired
  private ApplicationContext applicationContext;
  @PostConstruct
  void setup() {
    instance = applicationContext.getBean(Transactor.class); //不能写instance=this
  }
  private static Transactor instance;
}

代码中透出四个字:灵活,简洁!

2015/7/5 Update: 可惜的是,有时会抛出org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread (虽然stacktrace中是有代理类的)
目前实测改用Spring的TransactionTemplate是可以的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64318.html

相关文章

  • Lambda武装Java: 集合转换

    摘要:网上介绍和集合新特性的代码太千篇一律了,我来提供些不一样的。或者实现如下它的实现没有使用,因为是一种强大到能延迟处理和并行处理的,我们简单的集合操作不需要这么高级的能力。目前只写了三个方法,如果有需求,还可以扩充更多的方法。 网上介绍Java 8 lambda和集合新特性的代码太千篇一律了,我来提供些不一样的。虽然很简单,但也是工业级代码,不是网上抄来抄去的教学代码。权当给大家提供一个...

    Ajian 评论0 收藏0
  • java 8 实战》读书笔记 -第八章 重构、测试和调试

    摘要:通常,这种模式是通过定义一个代表处理对象的抽象类来实现的,在抽象类中会定义一个字段来记录后续对象。工厂模式使用表达式第章中,我们已经知道可以像引用方法一样引用构造函数。 一、为改善可读性和灵活性重构代码 1.改善代码的可读性 Java 8的新特性也可以帮助提升代码的可读性: 使用Java 8,你可以减少冗长的代码,让代码更易于理解 通过方法引用和Stream API,你的代码会变得更...

    gclove 评论0 收藏0
  • Effective Java 第三版 全文翻译

    摘要:本章中的大部分内容适用于构造函数和方法。第项其他方法优先于序列化第项谨慎地实现接口第项考虑使用自定义的序列化形式第项保护性地编写方法第项对于实例控制,枚举类型优先于第项考虑用序列化代理代替序列化实例附录与第版中项目的对应关系参考文献 effective-java-third-edition 介绍 Effective Java 第三版全文翻译,纯属个人业余翻译,不合理的地方,望指正,感激...

    galois 评论0 收藏0
  • 将函数式进行到底, Hooks 武装组件 - TXD 前端月刊 201905 期

    摘要:一个合格的中级前端工程师必须要掌握的个技巧对在毕业季还在找工作的同学,可以说很实用的,如果能全部掌握这些技巧,拿到几个应该是没有问题的,当然要注意平时的积累,能力要全面。而且该托管服务是完全免费的。 showImg(https://segmentfault.com/img/remote/1460000019376228?w=1790&h=898); 【阿里云 TXD 前端月刊】- 热门...

    eternalshallow 评论0 收藏0
  • 将函数式进行到底, Hooks 武装组件 - TXD 前端月刊 201905 期

    摘要:一个合格的中级前端工程师必须要掌握的个技巧对在毕业季还在找工作的同学,可以说很实用的,如果能全部掌握这些技巧,拿到几个应该是没有问题的,当然要注意平时的积累,能力要全面。而且该托管服务是完全免费的。 showImg(https://segmentfault.com/img/remote/1460000019376228?w=1790&h=898); 【阿里云 TXD 前端月刊】- 热门...

    xi4oh4o 评论0 收藏0

发表评论

0条评论

阅读需要支付1元查看
<