Is there any risk to call beginTransaction on one session multiple times? I mean for example:
session.beginTransaction();
session.saveOrUpdate(object1);
// .... some works
session.beginTransaction();
session.delete(object2);
// ... some other works
session.getTransaction.commit();
I did this and it seems there is no problem (any exception or warning). In fact I want to know what happens when I use transaction in such a way.
The javadocs give an explanation
beginTransaction() Begin a unit of work and return the associated Transaction object. If a new underlying transaction is required, begin the transaction. Otherwise continue the new work in the context of the existing underlying transaction. The class of the returned Transaction object is determined by the property hibernate.transaction_factory.
So - it has no effect, it continues using the existing transaction. So don't do it, as it might confuse readers (including you). You can have multiple transactions if you commit the first and then start the second.
Yes. There wont be any compile/run time exceptions thrown. However there are undesired results that might come up, resulting in the partly unsaved data. I have faced this issues sometime back.
Related
I have 2 questions related to each other
Q1 What exactly is a transaction boundary in hibernate/Spring Data JPA.
I am new to JPA , so please give a very basic example so I can understand as I tried to read multiple blogs but still not very clear.
Q2 And on top of it, what does this mean-
In hibernate, persist() method guarantees that it will not execute an INSERT statement if it is called outside of transaction boundaries, save() method does not guarantee the same.
What is outside and inside of a transaction boundary and how executions are performed outside boundaries?
A transaction is a unit of work that is either executed completely or not at all.
Transactions are fairly simple to use in a typical relational database.
You start a transaction by modifying some data. Every modification starts a transaction, you typically can't avoid it. You end the transaction by executing a commit or rollback.
Before your transaction is finished your changes can't be seen in other transactions (there are exceptions, variations and details). If you rollback your transaction all your changes in the database are undone.
If you commit your changes your changes become visible to other transactions, i.e. for other users connected to the same database. Implementations vary among many other things if changes become visible only for new transactions or also for already running transactions.
A transaction in JPA is a database transaction plus additional stuff.
You can start and end a transaction by getting a Transaction object and calling methods on it. But nobody does that anymore since it is error prone. Instead you annotate methods with #Transaction and entering the method will start a transaction and exiting the method will end the transaction.
The details are taken care of by Spring.
The tricky part with JPAs transactions is that within a JPA transaction JPA might (and will) choose to delay or even avoid read and write operations as long as possible. For example when you load an entity, and load it again in the same JPA transaction, JPA won't load it from the database but return the same instance it returned during the first load operation. If you want to learn more about this I recommend looking into JPAs first level cache.
A transaction boundary it's where the transaction starts or is committed/rollbacked.
When a transaction is started, the transaction context is bound to the current thread. So regardless of how many endpoints and channels you have in your Message flow your transaction context will be preserved as long as you are ensuring that the flow continues on the same thread. As soon as you break it by introducing a Pollable Channel or Executor Channel or initiate a new thread manually in some service, the Transactional boundary will be broken as well.
some other people ask about it - look it up.
If you do not understand something write to me again more accurately and I will explain.
I really hope I helped!
I'm using JPA and I begin a transaction before a function is called which will in turn store some data into the database. The transaction is then ended after the function call is executed. But I also use entityManager.flush() and entityManager.clear() guessing that memory will be freed on using clear(). before ending the transaction. Please do correct me. When I executed the program, it failed to roll back.
I also tried removing the flush() and clear(), still I'm not able to roll back. When can a roll back fail in my scenario when I'm using clear and flush?
I also use entityManager.flush() and entityManager.clear() guessing
that memory will be freed on using clear().
Well you should stop guessing and start reading some documentation.
EntityManager flushes on tx.commit() by itself, and entity manager is cleared when it is closed.
If you are using container manager transactions, you should rather not worry about flushing and clearing entity managers. If you are using JavaSE then your normal workflow with DB should look like this:
Create new entity manager
Start transaction
Do your job - delete/update/insert whatever
Commit transaction / Rollback if needed
Close entity manager
Normally this would be closed in small try-catch-finally block
EntityManager is lightweight and short living component. You should create one just when you need it, and close it right after you use it.
What is supposed to be a singleton instance, and created (most cases) only once is EntityManagerFactory
I have a method that has the propagation = Propagation.REQUIRES_NEW transactional property:
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(final UserBean userBean) {
//Some logic here that requires modification in DB
}
This method can be called multiple times simultaneously, and for every transaction if an error occurs than it's rolled back (independently from the other transactions).
The problem is that this might force Spring to create multiple transactions, even if another one is available, and may cause some performance problems.
Java doc of propagation = Propagation.REQUIRED says: Support a current transaction, create a new one if none exists.
This seems to solve the performance problem, doesn't it?
What about the rollback issue ? What if a new method call rolls back while using an existing transaction ? won't that rollback the whole transaction even the previous calls ?
[EDIT]
I guess my question wasn't clear enough:
We have hundreds of clients connected to our server.
For each client we naturally need to send a feedback about the transaction (OK or exception -> rollback).
My question is: if I use REQUIRED, does it mean only one transaction is used, and if the 100th client encounters a problem the 1st client's transaction will rollback as well ?
Using REQUIRES_NEW is only relevant when the method is invoked from a transactional context; when the method is invoked from a non-transactional context, it will behave exactly as REQUIRED - it will create a new transaction.
That does not mean that there will only be one single transaction for all your clients - each client will start from a non-transactional context, and as soon as the the request processing will hit a #Transactional, it will create a new transaction.
So, with that in mind, if using REQUIRES_NEW makes sense for the semantics of that operation - than I wouldn't worry about performance - this would textbook premature optimization - I would rather stress correctness and data integrity and worry about performance once performance metrics have been collected, and not before.
On rollback - using REQUIRES_NEW will force the start of a new transaction, and so an exception will rollback that transaction. If there is also another transaction that was executing as well - that will or will not be rolled back depending on if the exception bubbles up the stack or is caught - your choice, based on the specifics of the operations.
Also, for a more in-depth discussion on transactional strategies and rollback, I would recommend: «Transaction strategies: Understanding transaction pitfalls», Mark Richards.
If you really need to do it in separate transaction you need to use REQUIRES_NEW and live with the performance overhead. Watch out for dead locks.
I'd rather do it the other way:
Validate data on Java side.
Run everyting in one transaction.
If anything goes wrong on DB side -> it's a major error of DB or validation design. Rollback everything and throw critical top level error.
Write good unit tests.
We are trying to fix some issues on a testing harness, and having issues with a particular test, which basically tests a feature that creates an entity, does some processing and stores it in a database (Yes, the C in CRUD).
In the tearDown section of the fitnesse test, we execute a delete statement on that record. However, nothing is being deleted.
We suspect that this may be because the tearDown is executed before the SUT commits its transaction. So consequently, there's nothing to be deleted.
To try and fix this, we are making a pollable jdbc delete:
java.sql.Statement statement;
/*creates a statement*/
do{
recordsDeleted = statement.executeUpdate("delete...");
Thread.sleep(INTERVAL);
}while(recordsDeleted == 0);
So here comes the questions:
When is a jdbc transaction commited?
In the code above, will the updates be executed on the same transaction, or will a new transaction be created for each iteration of the do-while loop? (I'm inclined to think that they will be executed in the same transaction, since the java.sql.Connection holds the commit, rollback, etc methods).
Can you suggest another solution for this problem? I would think that this is quite common, but my teammates have not found any solution online, just the "poll until its deleted or timeout" suggestion.
I don't see anything wrong with your loop initially. You are calling statement.close() somewhere right? I assume the SUT is in another thread or is remote? Are you sure your delete criteria matches the input? Can you examine the database in another process to see if the create is making it to the database?
In terms of transactions, it depends on the database but typically there are no transactions by default. Typically auto-commit is enabled so each individual statement is executed and committed immediately. If you want to enable transactions then you need to disable auto-commit and then call databaseConnection.setSavePoint(). A transaction is committed when commit() is called. If the connection is closed (or rollback() called) then the transaction is rolled back.
I am using annotation based declarative approach for spring aop.
sample code
ClassA{
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
add()
{
method1();
method2();
method3();
}
}
But I have still doubt on use of propagation.does propagation.Requires_New means that each request will start new transaction.
Second question:
Does failure of any method like method2,method3 will cause the transaction to rollback?
I will be very happy if any can help me to leans transaction propagation.
can someone provide me a real world example where we need a participate in existing transaction.because I visualise that add function that we are using in above example will be independent for all users,or any other function will be independent to each user who is calling. I am not able to find example where other propagation behaviour like PROPAGATION_SUPPORTS ,PROPAGATION_MANDATORY,PROPAGATION_REQUIRES_NEW etc. are used
Answering this comment, not the actual question:
transaction are session specific or
request specific – Vish 3 hours ago
Neither. request and session are both web-specific scopes, while the Spring Transaction abstraction has nothing to do with web technologies.
The scope of #Transactional is per method invocation, as #Transactional is implemented through Spring AOP. The transactional state is kept in ThreadLocal variables which are initialized when the outermost #Transactional method is entered and cleared with commit or rollback when it is left. This whole abstraction works on Java method level, and hence does not require or profit from a web container.
And in response to this Question in the comment below:
thanks #sean,i am stil not able to get
answer where other propagation
behaviour like PROPAGATION_SUPPORTS
,PROPAGATION_MANDATORY,PROPAGATION_REQUIRES_NEW
etc are used. please refer above for
whole question
Here's the list of Propagation values with my comments:
MANDATORY
Support a current transaction, throw an exception if
none exists.
Does not start a new Transaction, just checks whether a transaction is active (must be inside either another #Transactional method call or a programmatically created transaction)
NESTED
Execute within a nested transaction if a current transaction
exists, behave like
PROPAGATION_REQUIRED else.
Start a nested transaction if a transaction exists, start a new transaction otherwise.
NEVER
Execute non-transactionally, throw an exception if a transaction
exists.
Does not start a transaction. Fails if a transaction is present.
NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one
exists.
Does not start a transaction. Suspends any existing transaction.
REQUIRED
Support a current transaction, create a new one if none
exists.
If a transaction exists, use that, if not, create a new one. In 95% of cases, this is what you need.
REQUIRES_NEW
Create a new transaction, suspend the current transaction if one
exists.
Always creates a new transaction, no matter if an existing transaction is present. If there is, it will be suspended for the duration of this method execution.
SUPPORTS
Support a current transaction, execute
non-transactionally if none exists.
Can use a transaction if one is present, but doesn't need one (and won't start a new one either)
In most cases, REQUIRED is what you need (hence it's the default in the #Transactional annotation). I have personally never seen any other value but REQUIRED and REQUIRES_NEW in use.
Transaction propagation indicates what should be the behaviour of the given method when it is invoked. REQUIRES_NEW means that a new transaction should always be started, even if there is an ongoing transaction.
If method1(), for example, defines REQUIRES_NEW, than it will execute in a new transaction.
An exception will rollback the current active transaction, yes.
Yes. Requires_New means that each request will start new transaction. and Yes failure in method2,method3 will cause the transaction to rollback, depending on the rollback properties.
check Transactional properties.