If autocommit is false in postgres will transaction be automatically roll backed - java

I am pretty new to model layer just need clarification that in our code if autocommit is false like
Connection conn = DBUtil.getConnection(userDb);
conn.setAutoCommit(false);
And we get an exception which is not related to postgres like
if (response.getValue() != null) {
conn.commit();
}
Where response object is arbitrary value,does the transaction be roll backed automatically in postgres.
Thanks

It depends. If a connection is closed, the transaction should be rolled back by the database. If you're using a connection pool, the transaction should be rolled back by the pool, when the connection is returned.
However this can depend on the driver, as well as the connection pool, so you should explicitly do commits and rollbacks instead of relying on the driver or the pool.

For be sure, better rollback transaction explicitly:
if (response.getValue() != null) {
conn.commit();
}
else {
conn.rollback();
}

Related

Will con.rollback() rollback already commited changes by con.commit()?

I am working on Legacy project now and it requires some deep knowledge of low level JDBC API
in some places I see code like this:
try {
con = ....
con.setAutoCommit(false);
//insert_1 pack to db
con.commit();
//insert_2 pack to db
con.commit();
//insert_3 pack to db
con.commit();
} catch (SQLException e) {
try {
con.rollback();
} catch (SQLException e) {
log.warn("SQLException on rolling back the destination connection. ", e);
throw e;
}
throw ex;
}
and sometimes con.rollback(); is not invoked in the the catch:
try {
con = ....
con.setAutoCommit(false);
//insert_1 pack to db
con.commit();
//insert_2 pack to db
con.commit();
//insert_3 pack to db
con.commit();
} catch (SQLException e) {
throw new MyBusinessException(ex);
}
Could you please explain difference from transaction standpoint ?
P.S.
I've read java doc for rollback but it doesn't answer my question.
Undoes all changes made in the current transaction and releases any
database locks currently held by this Connection object. This method
should be used only when auto-commit mode has been disabled. Throws:
SQLException – if a database access error occurs, this method is
called while participating in a distributed transaction, this method
is called on a closed connection or this Connection object is in
auto-commit mode See Also: setAutoCommit
The code looks incorrect.
There are several commits executed. This would mean that the explicit rollback could just rollback the state to the beginning of the last commit. This is, I guess, not what the rollback should do.
If no explicit rollback is called, at least in a pooled database connection (in a pooled database connection the connection is never closed, but reused) the already executed statements are still in transaction. I.e. calling here a rollback later would lead to strange kind of errors and also rolling back the last executed statements actually not related to the current business process. I see in the Hikari Connection Pool Implementation that dirty states are automatically rolled back, but maybe this correct behavior cannot be assumed for every implementation. E.g. the Apache DBCP is not that straight forward in the code and asking the maintainers if they are doing this should be helpful.
I see no close call.
For your questions this means the second code snippet should:
In a single non pooled connection not commit the last statements after the last commit, this is what would be correct (by accident).
In a pooled connection leave the transactions pending which could lead to the error that the next business logic committing something and reusing the connection will also commit this.

Does autoCommit var resets in c3p0 on close?

I am working with DB2. I created ConnectionPool for it. Some of the queries required to be executed in "aumoCommit = false" mode.
Connection con = ConnectionPool.getConnection // wrapper
con.setAutoCommit(false);
PreparedStatment ps = con.prepareStatement(// query... );
ps.setString(...);
ps.executeUpdate();
con.commit();
ps.close();
con.close();
con.setAutoCommit(true); // should be here ?
Question is: should i add con.setAutoCommit(true) line in the end or C3P0 resets state of every closed(returned to pool) Connection?
Edit: after a few comments, I add that my question is: should con.setAutoCommit(false) call be there in general or c3P0 reset state of this connection and nexct time this connection will be in con.setAutoCommit(false) by default?
c3p0 always releases Connections with autoCommit set to true, per the JDBC spec.
In general, c3p0 endeavors to make it true that nothing you do during an ordinary client session will have any effect on future client sessions. Once a Connection is checked back into the pool, c3p0 fully resets and restores its state.
The only place you can define Connection state that "sticks" across client sessions is in a ConnectionCustomizer's onAcquire(...) method, called before any client Session has been initiated. But this only works for Connection attributes whose value is undefined by the JDBC spec. Since autoCommit is required by spec to be true of a new Connection, and JDBC transparent Connection pooling requires pooled and new Connections be indistinguishable in application semantics, freshly checked-out Connections always have autoCommit set to true.

Cannot close a connection while a transaction is still alive Exception on connection.close()

I have a method that creates a Connection with Embedded Derby Database and performs a Select query on it.
public PersonMID findPersonMID(String personAlias, CodeUID aliasTypeCodeUID, LogicalDomainMID logicalDomainMID) throws SQLException
{
Connection connection = getConnection();
try
{
QueryExecutor<Long> findPersonIdByPersonAliasExecutor = FindPersonIdByPersonAliasDelegate.getExecutor(authority,connection, personAlias);
Long result = findPersonIdByPersonAliasExecutor.execute();
if(result == null)
{
return null;
}
return PersonMID.create(authority, result);
}
finally
{
JDBCAssistant.close(connection);
}
Here is what my query looks like:
select P.PRSON_ID from PRSON_ALIAS PA join PRSON P on P.PRSON_ID = PA.PRSON_ID and P.LOGICAL_DOMAIN_ID = ? where PA.PRSON_ALIAS_TYPE_CD = ? and PA.ALIAS = ?
When I run through this code, I get an Exception
JDBCException: java.sql.SQLException: Cannot close a connection while a transaction is still active.
But when I call Connection.commit() before I close the Connectionor set autoCommit true (it is set to false by default for my Connection) for my Connection, it is allowing me to successfully close the connection and get the reqired result.
But do I really need to call commit() for a Select operation? What's there to commit? Is there a lock somewhere that is not being released if I dont commit?
This post says I shouldn't have to do it. I should be able to close my connection without having to commit or rollback.
What am I missing?
If you are not in autoCommit mode, then a SELECT statement is in fact holding read locks, depending on your isolation level, and so committing a SELECT query is more than a no-op.
Yes, there is no change to the database, but the commit still tells the database engine that your transaction is finished looking at the data, and it can therefore allow other transactions to modify the data.
Here's some background material:
Isolation levels and concurrency; https://db.apache.org/derby/docs/10.12/devguide/cdevconcepts15366.html
Shared locks: https://db.apache.org/derby/docs/10.12/devguide/cdevconcepts842304.html

connection and session closing

I have the following code in the Try bloc :
// Session variable
Session session = null;
// Connection variable
Connection conn = null;
try {
...
// Get hibernate session
session = getHibernateTemplate().getSessionFactory().openSession();
// Get connection frojm session
conn = session.connection();
...
}catch{
...
}
And in the finally bloc i want to bloc all the related object of the connection with the database.
the closing of session makes us to close the connection ? or we have to have to close the connection before ?
Solution 1 :
finally{
try{if (conn!=null) conn.close();}ctach{}
try{if (session!=null) session.close();}catch{}
}
Solution 2 :
finally{
try{if (session!=null) session.close();}catch{}
}
In case of one of the two solutions before, can you explain the relationship between session and connection specially through pool way.
Second approach is enough. If you haven't set hibernate.connection.release_mode, then default (auto) is used. According documentation:
By default, a JDBC connection is held until the session is explicitly
closed or disconnected.
In case of pool, closing connection means that connection is returned to pool.
First, I like to know why you want to close connection in the code mentioned?
When you close a session hibernate makes sure that it does not hold any reference to the connection. In Hibernate 3.6.8, the call is delegated to the ConnectionManager. Check closeConnection() method. In Hibernate 4 when you call session.connection() what you get is a proxy and in hibernate 3, you are most likely get wrapper over connection, if connection pool is configured.
So your option is to debug session.connection() and session.close(), and decide whether you want to close the coneection or not.With the kind of information you provided, any answer here will be pure assumption.

Is rollback needed if java.sql.Connection#commit() throws exception?

According to JAVA documentation, Connection#commit() can throw SQLException. My question is whether or not a rollback should still be issued in this scenario.
For example:
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
con.commit();
} catch (SQLException e) {
if (con != null) {
// what if con.commit() failed, is this still necessary,
// will it hurt anything?
con.rollback();
}
} finally {
if (con != null) {
con.close();
}
}
I actually wrapped the con.rollback() call into another method which ignores any exceptions thrown by it, so I think I'm ok here. I just wondered if this was the best way of handling things.
Rollback is important even if commit failed, according to the Java 1.6 JDBC docs:
It is strongly recommended that an application explicitly commits or
rolls back an active transaction prior to calling the close method. If
the close method is called and there is an active transaction, the
results are implementation-defined.
This means that if you do not explicitly invoke rollback, some JDBC implementation might invoke commit before closing the connection.
Another good reason to rollback is as Xepoch suggested and when using a connection pool it is even more important.
When getting a connection from a connection pool, most implementations will execute connection.setAutoCommit(defaultAutoCommit) before giving you the connection and according to the JavaDocs:
If this method is called during a transaction and the auto-commit mode
is changed, the transaction is committed
If the connection.rollback() throws an exception - then it is a tricky one...
I would do explicit rollback just for clean-up purposes. Although changes won't be persisted in db either way, it seems nice to explicitly let database know that you're done here. Just like the way you close connection explicitly, without waiting for Connection object to be garbage-collected.
This is, obviously, not a technical answer and I would also be interested to learn whether there's a practical point in doing so.
"Returns an open connection?" If that connection is shared in a pool (and could be in the future) you don't want another transaction committing your earlier work. I've seen MANY customer/solution cases of plugging in pooled connection driver that comply with JDBC interfaces and Connection.close() can also be used to just return the Connection back to a pool.
Also, better try{}catch{} your rollback() (edit, just read your whole post, but I always like to log an exception on rollback)
The usual way I do this is:
boolean bSuccess = false;
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
bSuccess = true;
} catch (SQLException e)
{
}
finally
{
try
{
if (con != null)
{
if(bSuccess)
con.commit()
else
con.rollback();
con.close();
}
}
catch(SQLException sqle)
{
log("Log the error here");
// do nothing we tried
}
}
That being said I have never seen a commit or a rollback fail if the queries worked.
If you have pending transactions then most databases have tools to free them. Most app servers will keep retrying the commits and rollbacks until they can connect.
You might want to look at this post: Is it necessary to write ROLLBACK if queries fail?

Categories