9

Suppose I have a Repository class.

@Repository
class MyRepository {

    @Transactional
    void method1 () {
        // some logic here
    }

    void method2 () {
        // some logic here
        method1();
        // some logic here
    }
}

Is it possible to do that in String? And how this works?

JohnWinter
  • 1,003
  • 5
  • 12
  • 25
  • That particular example is a self-call and won't work with the usual proxy AOP. – chrylis -cautiouslyoptimistic- Jun 16 '15 at 13:26
  • And how can I make it work? – JohnWinter Jun 16 '15 at 13:27
  • Usually the controller is a non-transactional class that invokes the layer service, that is a good habit to have transactional methods inside. I don't see problems in it, if your problems requires this behaviour you can do it without problems. – lateralus Jun 16 '15 at 13:31
  • But my code doesn't work due to the reason described by @chrylis. I believe there is some hack how to make it work with non-standard proxy mechanism. – JohnWinter Jun 16 '15 at 13:32
  • I think there is a way to make it work by adding `@Autowired private ApplicationContext context;` to your repository and then when you call `method1` from `method2` you do it like this `((MyRepository)context.getBean(getClass())).method1()`. I would advise against this though. – Đuro Jun 16 '15 at 13:51
  • From Spring docs: When using proxies, the Transactional annotation should only be applied to methods with public visibility. If you do annotate protected, private or package-visible methods with the Transactional annotation, no error will be raised, but the annotated method will not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods. – randominstanceOfLivingThing Jun 16 '15 at 13:54
  • Does the second method always call the first one? Usually? Seldom? – chrylis -cautiouslyoptimistic- Jun 16 '15 at 18:54

4 Answers4

7

This does not work, since this a self call. See
Spring @Transaction method call by the method within the same class, does not work?

Depending on your application and its responsibilities, you could create another bean for method2(). Apart from that, DAO methods should usually not be annotated @Transactional. See
Where does the @Transactional annotation belong?

informatik01
  • 16,038
  • 10
  • 74
  • 104
user140547
  • 7,750
  • 3
  • 28
  • 80
  • it would be possible to make it work using org.springframework.aop.framework.AopContext ... but it is recommended not to use this. – André R. Jun 16 '15 at 13:37
1

This will not work because the method will go out of the scope of @Transaction when you will call the method2. But you can apply a hack and call method2 using this from method1 in the following way.

this.method2();
Farooq Khan
  • 592
  • 4
  • 15
1

You should use self injection to call a Transactional method from a non Transactional one as in Spring you can't simply call @Transactional method from the same instance because of AOP-proxy thing

@Repository
class MyRepository {

    @Autowired
    MyRepository selfTxMyRepository;

    @Transactional
    void method1 () {
        // some logic here
    }

    void method2 () {
        // some logic here
        selfTxMyRepository.method1();
        // some logic here
    }
}

See some explanation here: https://vladmihalcea.com/the-open-session-in-view-anti-pattern/

Jad Chahine
  • 6,849
  • 8
  • 37
  • 59
0

You cannot do that because Spring wraps methods that will be called from another class (service). If you call annotated methods from withing the same class, Spring will do nothing as it cannot wrap them.

informatik01
  • 16,038
  • 10
  • 74
  • 104
AntJavaDev
  • 1,204
  • 1
  • 18
  • 24