Say a connection is opened and auto commit is set to false to start a transaction. After the transaction is complete, I would like to rollback any changes to bring the database to the state it was before I started the transaction.
My problem is, that during the transaction the connection is closed, and thus all the changes are committed at that time.
Is there a way to rollback the state of the database to before the initial transaction started?
and yes I've tried using Savepoints to no avail.
This really depends on what you're doing, why and how.
If you have a reference to the transaction, you can rollback yourself.
If not, can you throw an exception at the end?
If all you want is to test things, why not use an embedded DB like H2 and start from scratch each time?
If H2 doesn't cut it, check out testcontainers.
Related
I have a spring (version 3.2.15) application that uses more than one connection in a transactional method.
My use case is:
Call to transactional method (which opens one connection)
Query for an entity (which opens and closes another connection)
Persist the entity
End of the method (closes the first connection)
The problem is that I have a limited number of connections, and I need to ensure that only one connection is used per transactional method. This problem causes a dead lock in my application because there are much more transactions opened than the number of connections available.
Is there any way that I can use the same connection spring uses to maintain the transaction on my method? I have already tried the hibernate option hibernate.connection.release_mode in after_statement mode, but an error occurs when hibernate is trying to commit the transaction.
I've read the spring transaction documentation but I cannot figure out how to configure spring to behave this way.
I have a Java app which uses JTA(Apache Geronimo) to manage transactions. The database in use is MySQL. App has a lot of begin and commit methods. However looking at the MySQL general log I could not find a single "Start transaction" query/command. The log is full of SET autocommit=1 and SET autocommit=0 with commit and rollback. Due to this, looking at logs I am unable to identify at what point the transaction began. I am not a Java guy and I could not find any helping resource on this either.
Start transaction and commit statements are used in MySql InnoDB. But In MySQL MyISAM, these commands are not valid so you need to use set autocommit = 0 instead of Start Transaction and set autocommit = 1 in place of commit;
InnoDB allows both the ways but MyISAM allows only set autocommit. Also, note that these commands perform somewhat similar work but they are not identical. And the use of set autocommit is not recommended in InnoDB.
For more information refer this question in StackOverflow.
MySQL's JDBC driver implements the Java JDBC API. The java.sql.Connection interface does not have a method to start a transaction.
A transaction begins implicitly when you execute an SQL query.
If the driver is in autocommit mode, the transaction is committed automatically once the SQL query finishes.
If the driver is not in autocommit mode, the transaction started by your query remains active until you call Connection.commit() or Connection.rollback().
See also How to start a transaction in JDBC?
Having the following problem of understanding why a connection session exists that goes on for 6 hours and also holding a lock and breaking the thread the question is rased if a connection of XADataSource (Oracle driver) needs a Java reference at all to be kept alive.
In terms of distributed transaction set to kept till it is explicitly ended (keep-xa-conn-till-tx-complete=true) I wonder how a driver could decide wether to close connection and commit a transaction once the GC recycled the connection. Is there even a way for the DBMS to do so?
So the question goes how does a DBMS decide wether to abandon a distributed transaction or not.
The DBMS does not decide to end the transaction, the transaction manager does.
The transaction manager is set up to run in your application containers, whether they are Spring, J2EE application servers, or something else. They have to "know" they are distributed transaction managers by being configured correctly. In a distributed transaction environment, where you have multiple transactional applications and/or services interacting to complete a transaction, they must all be able to support distributed transactions to make proper use of the XADataSources and send the right signals up and down the chain for commit vs rollback.
Presuming that you have the above situation, multiple applications and/or services participating in a distributed transaction, it sounds as if one of them is not configured correctly. Something in the chain is not truly a distributed transaction, so that when it completes it's only completing locally and not sending the signal back down the line. So the distributed transaction never completes, holding the connection open.
Check the configuration of every application and/or service participating in the transaction. Add logging output on each that details whether the transaction is a distributed one or not. If you can't do that, then dd logging output to each that records the start and end of the transaction. Find the latest point in the sequence of actions where you see an open-transaction but not a close-transaction. If you see that, it's likely the node right after it in the chain that is doing something wrong.
Good luck.
I have a non-web application that will run in background, during its run period I don't need any transactions. I must ensure that every jdbc operation should be automatically committed immediately, but spring jpa doesn't allow that happened.
How could I avoid TransactionRequiredException without transaction opened ??
Open a transaction. If you don't need an extended transaction and just want to do a quick update and commit it, you still need a transaction; just put #Transactional on the one method (or grab an EntityManager) and finish everything right there.
I have a transaction based application and it rolls the operation back on an error. However
in some cases, the rollback doesn't happen. ( Though its getting called from the application). Ours is a very complex application and there are chances that some code is directly committing the data. Is there a way to debug the commit to the database? (Either from java or from the database?). From java, we are not able to do this because, java.sql.Connection is an interface and the implementation is provided by sybase jconnect for which we don't have the source.
I am not sure this will help, but with this driver, this helps in tracing all the DML operations you perform on the database including commit & rollback. When you use p6spy
it logs every database hit into a log file, from where you can easily figure out where your application is performing a commit.
Apart from the above suggestion, I fell every database comes with some sort of monitoring tools, which with you can monitor which DML is fired within a span of time.