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

发布时间:2019-11-17 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了用Lambda武装你的Java: 灵活的事务脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

当你采用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> R apply(Supplier<R> 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是可以的。

脚本宝典总结

以上是脚本宝典为你收集整理的用Lambda武装你的Java: 灵活的事务全部内容,希望文章能够帮你解决用Lambda武装你的Java: 灵活的事务所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。