0

I'm currently working with some legacy code whereby transactions are rolled manually. Consider the following (example for illustrative purposes only, ignore syntax/design issues):

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

private PlatformTransactionManager transactionManager;
private DefaultTransactionDefinition txDefRequired = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED);
private DefaultTransactionDefinition txDefRequiresNew new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);


void createPosts(Map<String, String> posts){

    TransactionStatus status = transactionManager.getTransaction(txDefRequiresNew)
    try {
        // posts Map is made up for username:posttext key pair
        for (Map.Entry<String, String> entry : posts.entrySet()) {
            // Construct online post
            createPost(entry.getKey(), entry.getValue());
        }
        transactionManager.commit(status); 
    } finally {
        if (!status.isCompleted()) {
            transactionManager.rollback(status);
        }

    }
}

void createPost(String username, String text){

    TransactionStatus status = transactionManager.getTransaction(txDefRequired)

    // Construct online post
    OnlinePost p = new OnlinePost(text);
    User u = resolveUser(username);
    p.setUser(u);

    transactionManager.commit(status); // flush the session
}

User resolveUser(String username){

    TransactionStatus status = transactionManager.getTransaction(txDefRequired)
    User u = getUser(username);
    if(u == null)
        createUser(username);
    return u;
    transactionManager.commit(status); // flush the session

}

Would it be correct to say that in this particular flow, tx.commit() within the called methods, such as resolveUser(), will only serve to flush the session (flush-mode = auto) and return a new persistent entity with an artificial primary key generated and assigned to it so that you can use it later on in the same transaction?

dre
  • 1,027
  • 1
  • 11
  • 31

1 Answers1

1

No. A commit will invariably end the unit of work and push the updates to the database. A flush on the other hand, does not commit the changes to the db (as in commit them so that it's visible for everyone). You could technically rollback a flushed change. https://stackoverflow.com/a/14626510/2231632 for a possible duplicate.

And what you're looking for with the artificial primary key, you could use the Session.flush. But don't commit the txn if you want to use that key in the same txn.

Community
  • 1
  • 1
Praba
  • 1,373
  • 10
  • 30
  • 1
    The statement about `flush` is incorrect. The persistence provider is allowed to manifest the changes in the db (just not to commit them) however preserving the read-commited sematics. – kostja Apr 30 '14 at 10:40
  • Thanks for pointing it out. I should have been a bit more clearer. When I said push the changes to db, i was indeed thinking about changes that others can see. Edited now. – Praba Apr 30 '14 at 12:32
  • This has not been my experience. The persistent objects only get pushed to the database in the final outer commit (in createPosts()) but admittedly I've just noticed that my code uses a transaction manager, allow me to update the question. – dre Apr 30 '14 at 12:40