I have recently been playing with the sqlite4java library.
I think I have it pretty much figured out. The only think that bothers me is that I do not know how to switch off the auto-commit using this library. Can anyone please help?
A code example would be much appreciated.
Thanks in advance,
Boro
Jefromi and king_nak are correct - you just need to issue SQL statements that begin and end a transaction.
SQLiteConnection con = new SQLiteConnection();
con.exec("BEGIN");
// do transaction work - auto-commit is disabled
con.exec("COMMIT");
// auto-commit is enabled again
Edit: I confused sqlite4java with the sqliteJDBC package. So the below code will not help. I'm keeping it for reference nevertheless.
After you obtained the connection, just call setAutoCommit(false)
java.sql.Connection con = DriverManager.getConnection("jdbc:sqlite:/your/db/file", "user", "password");
con.setAutoCommit(false);
Referring to SQLite's C interface description:
The sqlite3_get_autocommit() interface returns non-zero or zero if the given database connection is or is not in autocommit mode, respectively. Autocommit mode is on by default. Autocommit mode is disabled by a BEGIN statement. Autocommit mode is re-enabled by a COMMIT or ROLLBACK.
So you disable auto-commit by a BEGIN TRANSACTION statement. No separate API function is present for this
Related
My hibernate config:
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.hbm2ddl.auto", "validate");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.id.new_generator_mappings", "false");
properties.put("hibernate.connection.autocommit", "true");
properties.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
properties.put("hibernate.connection.url", DBConnection.url);
properties.put("hibernate.connection.username", DBConnection.username);
properties.put("hibernate.connection.password", DBConnection.password);
Code example:
// pattern 1
Session s = sessionFactory.openSession();
ObjectA A = s.load(ObjectA.class, pk);
A.setAttr("abc");
s.update(A);
s.close();
// pattern 2
Session s = sessionFactory.openSession();
s.beginTransaction();
ObjectA A = s.load(ObjectA.class, pk);
A.setAttr("abc");
s.update(A);
s.close();
// pattern 3
Session s = sessionFactory.openSession();
Transaction tx = s.beginTransaction();
ObjectA A = s.load(ObjectA.class, pk);
A.setAttr("abc");
s.update(A);
tx.commit();
s.close();
Please ignore my compilation error. I am using hibernate in web application (without spring), and without using transaction, because I am using MySql database and MySql autocommit is true, so in turn, in hibernate, I make it as autocommit true as well. (I am using mysql-connector-java-5.1.23-bin.jar too).
Three of the pattern, I am only able to get pattern 3 works. I am totally confused now. I have few questions below:
1) I can't understand why pattern 1 is not working, all my select (via hibernate CriteriaBuilder or load) and insert (via hibernate session.save) works but only update doesn't work.
2) OK then I try using transaction like pattern 2, my hibernate auto-commit is true, so I assume when I close the session, the transaction should auto-commit but it doesn't work. Why?
3) Pattern 3 works, why I need transaction manager here? I want the jdbc to execute each single query in each transaction (one sql in one transaction), I don't worry the performance, but I have to include transaction here, why?
For pattern 1 and 2, I found that the update script is not even generated (based on hibernate log), the problem is not because script is generated but commit failed. Don't understand why? Please help...
PS:
Just wrap up some points for future reference after some trial and error:
1) Hibernate will only generate sql script upon the session.flush() is called but not tx.commit(), and session.flush() have to be called in Transaction block. without Transaction, it leads to exception. Explicit flush is not needed if the flush mode is auto, commit() will trigger flush.
2) Hibernate Transaction is not equivalent to database transaction, after some tries, I found that, if hibernate autocommit is false, yes, they are functionally equivalent and corresponding begin transaction script is generated via JDBC and send over to database (my guess only). If hibernate autocommit is true, no begin transaction is started although we declare it in hibernate Transaction tx = s.beginTransaction(), all the query will be autocommit and rollback will not work.
3) The reason of my case, session.save() (and also select) work without Transaction, it is a bit special because save have to be triggered in order to get the table identifier(primary key) and so sql script generated even without flush.
4) For pattern 2, I miss-understood, autocommit doesn't mean autocommit upon session closed, its true meaning should be autocommit upon each sql reach database. so pattern 2 will not work because there is no tx.commit, meaning there is no flush, so no sql script is generated. (whether tx.commit will be called automatically upon session.close, it depend on vendor implementation, some will be rollback.)
Conclusion, Transaction block is needed in Hibernate not matter what.
I think you have a bit of confusion. The transaction (org.hibernate.transaction) is not exactly a DB transaction.
Such Object are used by hibernate when you flush the Session (Session.flush) to bound the instruction in a single db transaction. In other word do not confuse Hibernate Session with DB session, nevertheless do not confue hibernate Sessio with db connection.
Most important is that by specificatio hibernate generate sql code only for what is included between a hibernate transaction. That's why pattern A and B doesn't work and doesn't generate sql code. More specifically the auto-commit in pattern B has no influence since the sql cod is never generated. Moreover, according with hibernate best pracitces, you have to remember to open and close a transaction even for simple select instruction. By the way a select should work even without transaction, but you may have some trouble.
To better understand the concept we can resume the architecture:
hibernate session: is a container, wich hold your hibernate object and your db operations as java objects, and many other things.
the hibernate transaction: is a transaction object referred to an hibernate session.
db connection: is your connection to DB
conenction pool: is a set ofdb connection.
What appen when a session is flushed can be resumed with the followoing step:
a connection is get from the connection pool
for each committed
transaction in your session a db connection is get from the pool,
the sql commands are generated and sent to DB
the db connection is put back on the pool
it is just a small recap, but hope this help
r.
I was setting con.setAutoCommit(false); as soon as I create connection so that nothing goes in DB uncommitted. But it turns out if you close the connection all transaction will be committed, no matter what your setAutoCommit() status is.
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection("jdbc:oracle:thin:#192.168.7.5:xxxx:xxx", "xxx", "xxx");
con.setAutoCommit(false);
st = con.createStatement();
String sql = "INSERT INTO emp (eid, name, dob, address) VALUES (?, ?, ?, ?)";
PreparedStatement statement = con.prepareStatement(sql);
statement.setInt(1, 8 );
statement.setString(2, "kkk" );
statement.setDate(3, date );
statement.setString(4, "pppp" );
pst = con.prepareStatement(sql);
int rowsInserted = statement.executeUpdate();
//con.commit ();
System.out.println ("rowsInserted "+rowsInserted);
con.close ();
Even after commenting con.commit (); row is being inserted when connection closes so I was wondering what is the use of con.commit (); ?
Another answer says it's vendor specific:
If a Connection is closed without an explicit commit or a rollback; JDBC does not mandate anything in particular here and hence the behaviour is dependent on the database vendor. In case of Oracle, an implict commit is issued.
It does not make sense.Thanks.
Logging off of Oracle commits any pending transaction. This happens whether you use sqlplus or the JDBC driver through conn.close(). Note that it's not the driver that issues the commit it's the server. During logoff the server commits pending changes. From your Java program you can always call conn.rollback() before calling conn.close() if you want to make sure that pending changes are not committed.
You asked what is the use of conn.commit(). It's used to explicitly commit a transaction at a specific point of your business logic. For example if you cache connections in a connection pool, you can disable auto-commit and commit pending changes before releasing the connection back to the pool. Some people prefer enabling auto-commit mode (which is the default in JDBC) and not worry about explicitly committing or rolling back changes. It depends on your business logic. You can ask yourself: will I ever need to rollback a DML execution? If the answer is yes then you should disable auto-commit and explicitly commit transactions.
Oracle documentation provides a very good explanation of when and why this should be used. Please go through the same!
If your JDBC Connection is in auto-commit mode pro grammatically or by default, (this is by default, fyi), then every SQL statement is committed to the database upon its completion.
You can refer to this question for more detailed explanation on the same topic.
con.commit() is an explicit commit and you can call it whenever you have to commit the transaction. In your case there is no explicit commit or rollback though you have set AutoCommit to false. The Oracle Database commits all the transactions of a session which exits the connection gracefully. If the session terminates abnormally then it rolls back the transactions.
I'm running some load tests on our system and I notice a massive number of "SET autocommit=0" and "SET autocommit=1" queries being executed. Something around 25,000 within 1 minute. I'm trying to figure out what is causing this and how to get rid of it.
We use the following technologies:
MySQL
Hibernate
Hikari
Spring
Tomcat
I have tried the following but it did not seem to help:
"SET autocommit = 0" in MySQL
Added the elideSetAutoCommits property in the db connection URL. "jdbc:mysql://localhost/db_name?useUniCode=true&characterEncoding=UTF-8&pinGlobalTxToPhysicalConnection=true&elideSetAutoCommits=true"
Could someone point me towards what might be causing these queries?
Could someone point me towards what might be causing these queries?
Your queries are the consequence of Connection#setAutoCommit(boolean) which is used to switch from the default mode that is auto-commit mode to transactional mode in order to insert/update/delete/read data within a transaction.
The common code is :
// Switch to transactional mode which actually triggers a SET autocommit = 0
con.setAutoCommit(false);
try {
// Some operations on the db
con.commit();
} finally {
// Switch back to auto-commit mode which actually triggers a SET autocommit = 1
con.setAutoCommit(true);
}
Here is a good link that explains how transactions work in JDBC.
If you know that your pool of connections will always be used to get connections in transactional mode, you can set the default mode in the configuration of Hikari thanks to the parameter autoCommit to set to false this way the connections will be already in transactional mode such that it won't be needed anymore to modify the mode.
This property controls the default auto-commit behavior of connections
returned from the pool. It is a boolean value. Default: true
More details about the configuration of Hikari here.
I'm using latest derby10.11.1.1.
Doing something like this:
DriverManager.registerDriver(new org.apache.derby.jdbc.EmbeddedDriver())
java.sql.Connection connection = DriverManager.getConnection("jdbc:derby:filePath", ...)
Statement stmt = connection.createStatement();
stmt.setQueryTimeout(2); // shall stop query after 2 seconds but id does nothing
stmt.executeQuery(strSql);
stmt.cancel(); // this in fact would run in other thread
I get exception "java.sql.SQLFeatureNotSupportedException: Caused by: ERROR 0A000: Feature not implemented: cancel"
Do you know if there is way how to make it work? Or is it really not implemented in Derby and I would need to use different embedded database? Any tip for some free DB, which I can use instead of derby and which would support SQL timeout?
As i got in java docs
void cancel() throws SQLException
Cancels this Statement object if both the DBMS and driver support aborting an SQL statement. This method can be used by one thread to cancel a statement that is being executed by another thread.
and it will throws
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
you can go with mysql.
there are so many embedded database available you can go through
embedded database
If you get Feature not implemented: cancel then that is definite, cancel is not supported.
From this post by H2's author it looks like H2 supports two ways to timeout your queries, both through the JDBC API and through a setting on the JDBC URL.
Actually I found that there is deadlock timeout in derby as well only set to 60 seconds by default and I never have patience to reach it :).
So the correct answer would be:
stmt.setQueryTimeout(2); truly seems not working
stmt.cancel(); truly seems not implemented
But luckily timeout in database manager exists. And it is set to 60 seconds. See derby dead-locks.
Time can be changed using command:
statement.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
"'derby.locks.waitTimeout', '5')");
And it works :)
I am using JTDS to connect to MS-SQL 2005. I am using c3p0 as the DB Connection pool, configured with Spring.
I am randomly getting an SQLException: Invalid state, the ResultSet object is closed in a Groovy script in which I have passed a reference to the connection pool. The script is executed by a timer every so often. By random, I mean that the script works perfectly 99% of the time, but when it fails, it will do so a couple of times, then go back to working correctly again, picking up where it left off. All of the critical work is done in a transaction, pulling off of a Message Queue.
Logic below:
//passed into the groovy context
DataSource source = source;
Connection conn = source.getConnection();
...
//Have to omit proprietary DB stuff... sorry...
PreparedStatement fooStatement = conn.prepareStatement("INSERT INTO foo (x,y,z) VALUES (?,?,?) select SCOPE_IDENTITY();");
ResultSet identRes = fooStatement.executeQuery();
//This is where the execption is thrown.
identRes.next();
...
try{
log.info("Returning SQL connection.");
conn.close();
}catch(Exception ex){}
There is a separate timer thread that runs a similar groovy script, in which we have not seen this issue. That script uses similar calls to get the connection, and close it.
Originally, we thought that the second script may have been grabbing the same connection off the pool, finishing first, then closing the connection. But c3p0's documentation says that calling conn.close() should simply return it to the pool.
Has anyone else seen this, or am I missing something big here?
Thanks.
We solved this... C3P0 was configured to drop connections that were checked out longer than 30 seconds, we did this to prevent dead-lock in the database (we don't control the tuning). One of the transactions was taking horridly long to complete, and C3P0 was dropping the connection, resulting in the ResultSet Closed error. Surprisingly, however, C3P0 was not logging the incident, so we didnt see this in the application's logs.