2
votes

Not sure if 'scope' is the correct term here.

I am using Spring for JPA transaction management (with a Hibernate underneath). My method to preform database transaction is private, but since you can only set @Transactional on a class or on a public method

Since this mechanism is based on proxies, only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!

I have set the public entry point of the class as @Transactional.

@Transactional
public void run(parameters) {
    //First non-database method, takes a decent amount of time
    Data data = getData();
    //Call to database
    storeData(data);
}

private storeData(data) {
    em.persist(data);
}

Is this bad practice? Is Spring keep an open transaction for longer then needed here? I was thinking of move the storeData() method to a DAO class and making it public, but as academic point, I wanted to know if refactoring to public would have any performance benefit.

3
I have two answers here that, if I understand them correctly, are saying opposite things, can anyone else weigh in on this question? - James McMahon
The question stackoverflow.com/questions/1079114 has some relevance to this one. - James McMahon

3 Answers

1
votes

If there's heavy contention on the DB, keeping transactions as small as possible is definitely crucial -- much more important than public vs private distinctions, which, per se, don't affect performance and scalability. So, be practical...!

1
votes

The transaction scope is has no effect until your code does something which interacts with the transaction context, in this case the storeData() method. The fact that getData() is non-transactional should not affect the performance on concurrency of your code, since any database locking will only happen when storeData() is reached.

0
votes

As everyone pointed we should keep transaction as small as possible, so that connection remains available for other request. Can this be refactored as this

public void run(parameters) {
  Data data = getData();
  storeData(data);                                                             
 }

@Transactional
public storeDate(data){em.persist(data)}