Does Spring issue a commit to the database after each package call, or does it only commit after everything is done?
I am using Spring and Struts. In my controller class, I am calling many database packages with spring stored procedure in a DAO class. each call has its only method in the DAO class
My question is, will Spring commit only after all calls have been made from the controller class and the controller has finished, or will it commit after each execution of a SpringStoredProcedure?
my_package_getusers = SpringStoredProcedure.getStoredProcedureCompiled(getJdbcTemplate()
....
my_package_getusers.execute(params).get("result")
Spring utility classes from spring-jdbc don't make any commits. The responsibility for commiting transaction belongs to the spring-tx (transaction support.
This is usually made by placing #Transactional annotation on the method that should be run in transaction scope. So if you have method
#Transactional
public void doSomething(SomeClass arg) {...}
entering that method will create new transaction, and that transaction will be commited after leaving the transaction, if the transactional context doesn't exist. However, if that method is called from other method annotated with #Transactional, the parent transaction context will be used.
As alternative, you can use org.springframework.transaction.support.TransactionTemplate to gain more control over transactions (for example, launching separate transaction from transactional context).
Example:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
// do something in trancation)
}
});
Note, that on some databases, such as Oracle, you can commit transaction within stored procedure, which will persist all changes made in existing transaction, and the new transaction will follow.
Related
I'm currently implementing my first spring boot application after years of JEE.
I am wondering about JPA / Hibernate behaviour. In JEE, once persisted or "find" an #Entity, all changes to this Entity are populated automatically by the JPA implementation to the database without any need to call persist(), flush() etc.
Now with a CrudRepository changes are only stored to the database if I explicitely call save().
My CrudRepository:
public interface UserAccountRepository extends CrudRepository<UserAccount, Long> {
public Optional<UserAccount> findByEmail(String email);
public Optional<UserAccount> findByVerificationCode(String verificationCode);
}
Example code:
public void updateUser(Long userId, String newName) {
UserAccount userAccount = userAccountRepository.findById(userId)
.orElseThrow(() -> new NotFoundException("Userid not found"));
userAccount.setLastName(newName);
//Stop here in JEE
userAccountRepository.save(userAccount);
}
In a JEE implementation right after .setLastName the change would be persisted to the database by Hibernate. In my spring-boot service it istn't. It's usually explicitely necessary to issue .save() any idea why and how I could gain the same behaviour like in JEE?
Actually Spring boot Repository uses JPA behind the scene to persist entity to the database. but I want to explain what happen behind the scene. You know there is an EntityManager which has a Persistence Context. When EntityManager created, it will attach itself to the current TransactionManager so that when that transaction committed all data within that Persistence Context will be committed to the database or on the other hand when transaction RollBack all data within that Persistence Context will be roll backed. Here in Spring Repository you can see that there is no Persistence Context explicitly. This Persistence Context exist but works behind the scene and when findById method return and deliver you the entity, that entity is not attached to persistence Context actually this context is closed when findById return.
But Spring Repository make all this proccess transparent to the user since it uses EntityManager and Transaction Manager behind the scene. actually it is the magic wand of Spring that let you omit all these boilerplate code. But this magic didn't come without any drawback, in your updateUser method you don't open and you don't commit any transaction but they acctually opened and committed two times behind the scene, once when you call findById method, it open transaction, fetch data and commit it. And again when you save data here again transaction open, and Persistence Context content save to database when transaction committed. imagine you have some transactional process in your special method in that case you should think about that specially.
In Spring how can we make sure that certain operations are always executed together. If any one of them fails, the entire transaction needs to be rolled back. I searched this a lot and found #Transactional(propagation = Propagation.REQUIRED) annotations and TransactionTemplate.execute() methods close to my problem. Kindly clarify and help.
Both #Transactional and TransactionTemplate ensure atomicity. #Transactional is for declarative transaction management, TransactionTemplate is for programmatic transaction management. You should choose one.
The idea of transaction propagation applies only to declarative transaction management and defines a transaction behaviour when it is executed in more than one method. Note that Propagation.REQUIRED is default for Transactional.propagation. It means Support a current transaction (that is if a transaction was already started in the calling method) or create a new one if none exists.
#Transactional(propagation = Propagation.REQUIRED
May solve your problem.
Suppose in your Impl there is a method Excecute.Inside Excecute method there are other M1(),M2(),M3(),M4(),M5() methods.
May be you trying to say if for M1(),M2().M3().M4() methods Db operation succedded and at last for M5() it throws some exception then M1() to M5() all db operation should be rollback
Execute(){
M1();
M2();
M3();
M4();
M5();
if(Any error in any methods transaction will be roll back).As single trasaction object is used for all methods i.e(M1 to M5) when #Transactional(propagation = Propagation.REQUIRED is used.
}
You can create a single method that delegates to the two database calls and annotate that with #Transactional, e.g.
#Transactional
public void atomicOperation(...) {
dbCall();
logicOperation();
}
If either one fails, e.g. an exception is thrown, the entire operation will rollback. The Spring Reference Documentation has dedicated a chapter for transactions, for example there is information about #Transactional settings and Transaction propagation.
I need to commit transactions from CMT bean by hand. There is a loop which processes multiple records and each record should be processed in its own transaction. I wanted to mark method transaction support as NOT_SUPPORTED and then control transaction from method. However I could not retrieve a UserTransaction instance neither from SessionContext neither injecting it as a JNDI resource java:/module/UserTransaction.
Are there any chance to process multiple records in CMT bean in their own transactions without introducing new BMT bean for such processing?
You should not mess around transactions yourself if you use CMT.
I recommend you create a method for the operation needs to be in transaction, mark it as REQUIRES_NEW, then call it from the loop.
Everytime the method is called, the current transaction (if any) will be suspended and a new transaction will be started for the operation.
Something like this:
#EJB
SomeEJBLocal anotherme;
public void loop() {
for(/* something */) {
anotherme.single();
}
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void single() {
// do stuff
}
You will have to inject another instance of the EJB and call single in order for the container to process the transaction aspects.
The situation is as follows:
Method1 has four database update methods in it. The Method1 is annotated using the Spring transaction management semantics.
Method2 has a database read method in it and it is invoked after Method1 has finished executing all its database updates. Method2 is also annotated using the Spring transaction semantics.
There's a web request that comes in, the controller intercepts the request and invokes method1 and then method2.
A transaction is wrapped around the web-request as well.
What I am interested in knowing is:
1.How does Spring know to commit the database updates upon a successful transaction? Is there some reference to the Spring implementation that does the transaction management?
2.Since we have a hierarchy of transactions:
Transaction around the web-request->Transaction with Propagation=RequestNew for Method1->Transaction with Propagation=Required for Method2, how does Spring do the transaction management to ensure the transactions are executed within the proper context with the right order?
In short, it will be great to get a play by play account of how Spring performs the transaction management in all its grittiest details or a reference to documentation that doesn't simply hand-wave an explanation centered around JTA or some other acronym.
Thanks
Lets make some basic statements.
A transactional context is an environment where some special properties (database session) are made available to the application runtime which are otherwise not available. A Transaction Context is generally used to scope a transaction.
Spring uses, AOP Proxies and XML metadata to achieve a Declarative transaction management.
Annotations are used to mark the Transaction Propagation behavior of a particular method.
Spring uses Interceptor Mechanism to apply the transaction over the methods.
Here I am reusing the example give by #stacker above
MyClass{
#Transactional
public void sequence() {
method1();
method2();
}
#Transactional
void method1() {
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
void method2() {
}
}
You can also achieve the same functionality using xml configuration as well. Lets take this as its popular and widely used.
At the time of deployment
Spring framework checks the xml configuration files (famed applicationContext.xml) and depending on the configuration, scans the code for #Transactional annotation (assuming that the configuration is mentioned as annotation based).
After this, it generates AOP proxies for methods marked for transaction. In simple terms, these proxies are nothing but wrapper around the concerned methods.
Within these wrapper methods, before and after a Transaction Advisor code is also generated depending on the configuration (namely the transaction propagation).
Now when these wrapper methods are invoked Transaction Advisor comes into picture before and after the actual method call. .
Representing the same in pseudo code for the example above
ProxyMyClass{
MyClass myclass;
.
.
.
sequence(){
//Transaction Advisor code (Typically begin/check for transaction)
myclass.sequence();
//Transaction Advisor code(Typically rollback/commit)
}
.
.
.
}
This is how spring managers the transaction. A slight oversimplification though.
Now to answer your questions,
.How does Spring know to commit the database updates upon a successful transaction? Is there some reference to the Spring implementation that does the transaction management?
Whenever you call a method under transaction, you actually call a proxy which first executes the transaction advisor (which will begin the transaction), then you call the actual business method, once that completes, another transaction advisor executes (which depending on way method returned, will commit or rollback transaction).
Since we have a hierarchy of transactions: Transaction around the web-request->Transaction with Propagation=RequestNew for Method1->Transaction with Propagation=Required for Method2, how does Spring do the transaction management to ensure the transactions are executed within the proper context with the right order?
In case of transaction hierarchy, the spring framework generates the Transaction Advisor checks accordingly. For the example you mentioned,
for method1 (RequestNew ) Transaction Advsor code (or transaction Advice) would be to create a new transaction always.
for method2 (Required ) Transaction Advisor code (or transaction Advice) would be check for existing transaction and use the same if it exists or else create a new transaction.
There is an image on the spring documentation page which very nicely summarizes these aspects.
Hope this helps.
Controller
#Transactional
public void sequence() {
method1();
method2();
}
#Transactional
void method1() {
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
void method2() {
}
The default propagation is REQUIRED (Support a current transaction, create a new one if none exists.) Therefore m1 will use the Transaction started in the Controller. m2 is annotated as REQUIRES_NEW ( Create a new transaction, suspend the current transaction if one exists.) The order of the transaction is the order you call the transactional methods.
Controller
begin tx1
|--------------------> m1 (uses tx1)
|
| begin tx2
|--------------------> m2 (uses tx2)
| commit tx2
commit tx1
Have you read the Spring documentation? Basically AOP is used to manage the transaction. You should also read the AOP documentation. If the AOP documentation is not enough I suggest you go through the code. Stepping through the code in debug mode with break-point would be good.
I've seen a method in a Service class that was marked as #Transactional, but it was also calling some other methods in that same class which were not marked as #Transactional.
Does it mean that the call to separate methods are causing the application to open separate connections to DB or suspend the parent transaction, etc?
What's the default behavior for a method without any annotations which is called by another method with #Transactional annotation?
When you call a method without #Transactional within a transaction block, the parent transaction will continue to the new method. It will use the same connection from the parent method (with #Transactional) and any exception caused in the called method (without #Transactional) will cause the transaction to rollback as configured in the transaction definition.
If you call a method with a #Transactional annotation from a method with #Transactional belonging to the same Spring Bean, then the called methods transactional behavior will not have any impact on the transaction. But if you call a method with a transaction definition from another method with a transaction definition, and they belong to different Spring Beans, then the code in the called method will follow its own transaction definitions.
You can find more details in the section Declarative transaction management of spring transaction documentation.
Spring declarative transaction model uses AOP proxy, so the AOP proxy is responsible for transactions creation. The AOP proxy will be active only if the called method belong to a different Spring Bean than the caller one.
Does that mean the call to separate methods are causing the application to open separate connections to DB or suspend the parent transaction, etc?
That depends on a propagation level. Here are all the possible level values.
For example in case a propagation level is NESTED a current transaction will "suspend" and a new transaction will be created ( note: actual creation of a nested transaction will only work on specific transaction managers )
What's the default behavior for a method without any annotations that is called by another method with #Transactional annotation?
The default propagation level ( what you call "behavior" ) is REQUIRED. In case an "inner" method is called that has a #Transactional annotation on it ( or transacted declaratively via XML ), it will execute within the same transaction, e.g. "nothing new" is created.
#Transactional marks the transaction boundary (begin/end) but the transaction itself is bound to the thread. Once a transaction starts it propagates across method calls until the original method returns and the transaction commits/rolls back.
If another method is called that has a #Transactional annotation then the propagation depends on the propagation attribute of that annotation.
The inner method will affect the outer method if the inner method is not annotated with #Transactional.
In case inner method is also annotated with #Transactional with REQUIRES_NEW, following will happen.
...
#Autowired
private TestDAO testDAO;
#Autowired
private SomeBean someBean;
#Override
#Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
testDAO.insertUser(user);
try{
someBean.innerMethod();
} catch(RuntimeException e){
// handle exception
}
}
#Override
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
throw new RuntimeException("Rollback this transaction!");
}
The inner method is annotated with REQUIRES_NEW and throws a RuntimeException so it will set its transaction to rollback but WILL NOT EFFECT the outer transaction. The outer transaction is PAUSED when the inner transaction starts and then RESUMES AFTER the inner transaction is concluded. They run independently of each other so the outer transaction MAY commit successfully.