用私有方法保存实体

时间:2019-03-01 15:36:07

标签: java spring hibernate spring-transactions

我有一个Ingestion类,它公开了一个单一方法ingest。此方法处理传递形式的每个部分(第1部分,第2部分等)。

每个部分都有专用方法,可以在处理实体时保存它。我知道@Transactional对私有方法没有影响,但是我不想公开这些方法,而是想使用@Transactional提供的功能。

我希望确保每个部分都以自己的Transaction完成;我可以通过“ AspectJ”(如其他SO答案所建议的)来完成此操作,而不是使用Spring的现成实现,但是我试图避免由于会导致系统范围内的更改。

对其他方法有何想法?

下面提供的伪代码给出了有关类结构的一般概念:

public Class Ingestion {
   // Autowired Repo's
   ...
   ...
   @Transactional
   public void ingest(Form form){
       this.processSection1(form);
       this.processSection2(form);
       this.processSection3(form);
   }

   @Transactional
   private void processSection1(Form form){
     // do specific section 1 logic
     section1Repo.save(form);
   }

   @Transactional
   private void processSection2(Form form){
     // do specific section2 logic
     section2Repo.save(form);
   }

   @Transactional
   private void processSection3(Form form){
     // do specific section3 logic
     section3Repo.save(form);
   }
}

================================================ ========================= 这不是注释中标记的重复问题。我知道@Transactional在私有方法上不起作用。我的问题更像是“我们如何无需使用AspectJ就能解决春季AOP问题”

2 个答案:

答案 0 :(得分:0)

之所以不起作用,是因为诸如@Transactional之类的注释会添加其他功能,这些功能会被包装实际对象的Spring代理对象所拦截。但是,当您使用this关键字在对象上调用私有方法时,您将直接进入真实对象并绕过代理。

解决此问题的一种方法是将对象@Autowire放入自身,然后通过该自动装配变量进行事务调用。您仍然可以通过这种方式访问​​私有方法,并且将调用Spring管理的代理而不是裸对象。

答案 1 :(得分:0)

您可以将这三种处理方法提取到另一个类中,将它们公开,但是将类构造函数的访问级别设置为本地包(但不是私有的,因为Spring无法使用私有构造函数代理类),因此没有类来自其他程序包可以访问这些方法的原因仅在于它们无法实例化其类。它并没有完全隐藏这些方法,但是可能满足您的需求。这个技巧也可以通过内部类来完成(请注意,必须使用程序包本地访问声明它)。

要完全隐藏这些方法,您可以通过注入((unsigned __int128)1ULL << 64) - 1 bean并在私有方法中使用其TransactionTemplate方法来使用声明式事务管理。此功能是现成的。查看更多here

此外,请注意,要在执行方法execute中的方法B上创建新事务时,必须将方法A声明为B,传播类型为@Transactional 。否则,任何嵌套方法都将在由初始调用方法开始的同一事务中被调用。