Hi I'm trying to clean up my code to remove errors stating that my db connection was opened but not closed correctly.
If I have a db.open() then a few try catch statements around db query's then a db.close() following the try catch will it use the same db connection within the try catches or does java discretely run the try catch statements so the db connection is not available.
In short, should i have code something like this:
db.open();
try {
// here
db.getThings()
} catch () {
// there
}
try {
// here 2
db.getMoreThings()
} catch () {
// there 2
}
db.close();
Or this:
try {
// here
db.open();
db.getThings()
db.close();
} catch () {
// there
}
try {
// here 2
db.open();
db.getMoreThings()
db.close();
} catch () {
// there 2
}
I'd have thought the first solution of opening one db connection is the better one. But i'm running into issues with not closing db connections and i'm at the point of thinking there's a fundamental issue with my design.
I've also tried opening the connection in onResume() then close in onPause() but still having problems.
There is a recommendation to close DB connection as soon as you selected data, so in my app I mainly use the following template:
db.open();
try {
// select data
} finally {
db.close();
}
it worked for me.
Related
I am working in java hibernate and mysql. I want to use transaction settimeout for a payment functionality of application. I just test the code as below for settimeout to work.
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
Session session = (Session) threadSession.get();
session.getTransaction().setTimeout(5);
tx=session.beginTransaction();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(session.getTransaction().isActive()) {
System.out.println("session active");
}
else {
System.out.println("session inactive");
}
threadTransaction.set(tx);
}
}
catch (HibernateException e) {
throw new HibernateException("", e);
}
But it print session active, means the timeout doesnt work. What is the reason? please help !
Hibernate is pretty good at doing nothing as long as nothing needs to be done (efficiency and such). I think that is what your test shows, not that the the timeout is not working for what it was intended to do:
"... ensuring that database level deadlocks and queries with huge result sets are limited by a defined timeout."
Also note that "setTimeout() cannot be called in a CMT bean ..."
Test the transaction timeout with some code that does what the transaction timeout was intended for and I think you'll find it working properly.
I have a JDBC code where there are multiple Savepoints present; something like this:
1st insert statement
2nd insert statement
savepoint = conn.setSavepoint("S1");
1st insert statement
2nd update statement
savepoint = conn.setSavepoint("S2");
1st delete statement
2nd delete statement
savepoint = conn.setSavepoint("S3");
1st insert statement
2nd delete statement
savepoint = conn.setSavepoint("S4");
Now in the catch block, I am catching the exception and checking whether the Savepoint is null or not; if yes then rollback the entire connection else rollback till a Savepoint. But I am not able to understand till which Savepoint shall I roll back.
Will it be fine if I change all the savepoint names to "S1" ? In that case how will I understand how many till Savepoint did work correctly?
Please advise how to understand until what Savepoint the work was performed correctly?
Would view this as multiple transactions. Hence you could handle this with multiple try/ catch blocks. You also seem to be overwriting the savepoint objects hence it would be not feasible to rollback.
More info.
JDBC also supports to set save points and then rollback to the specified save point. The following method could be used to define save points.
SavePoint savePoint1 = connection.setSavePoint();
Rollback a transaction to an already defined save point using rollback call with an argument.
connection.rollback(savePoint1);
Reference.
https://www.stackstalk.com/2014/08/jdbc-handling-transactions.html
In such cases, I've found out the tricky part is to make sure you commit the transaction only if all inserts succeed, but rollback all updates if any insert fails. I've used a savepoint stack to handle such situations. The highly simplified code is as follows:
A connection wrapper class:
public class MyConnection {
Connection conn;
static DataSource ds;
Stack<Savepoint> savePoints = null;
static {
//... stuff to initialize datasource.
}
public MyConnection() {
conn = ds.getConnection();
}
public void beginTransaction() {
if (savePoints == null) {
savePoints = new Stack<Savepoint>();
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
} else {
savePoints.push(conn.setSavepoint());
}
}
public void commit() throws SQLException {
if (savePoints == null || savePoints.empty()) {
conn.commit();
} else {
Savepoint sp = savePoints.pop();
conn.releaseSavepoint(sp);
}
}
public void rollback() throws SQLException {
if (savePoints == null || savePoints.empty()) {
conn.rollback();
} else {
Savepoint sp = savePoints.pop();
conn.rollback(sp);
}
}
public void releaseConnection() {
conn.close();
}
}
Then you can have various methods that may be called independently or in combination. In the example below, methodA may be called on its own, or as a result of calling methodB.
public class AccessDb {
public void methodA(MyConnection myConn) throws Exception {
myConn.beginTransaction();
try {
// update table A
// update table B
myConn.commit();
} catch (Exception e) {
myConn.rollback();
throw e;
} finally {
}
}
public void methodB(MyConnection myConn) throws Exception {
myConn.beginTransaction();
try {
methodA(myConn);
// update table C
myConn.commit();
} catch (Exception e) {
myConn.rollback();
throw e;
} finally {
}
}
}
This way, if anything goes wrong, it rolls back fully (as a result of the exception handling), but it will only commit the entire transaction instead of committing a partially completed transaction.
I'm trying to access my database while using SqlJet Transactions, but I get this error all the time
org.tmatesoft.sqljet.core.SqlJetException: MISUSE: error code is MISUSE
Here is my code:
SqlJetDb db = null;
try {
File dbFile = new File(Configuration.DATABASE_NAME);
db = SqlJetDb.open(dbFile, true);
db.getOptions().setAutovacuum(true);
db.beginTransaction(SqlJetTransactionMode.READ_ONLY);
ISqlJetTable table = db.getTable("customers");
ISqlJetCursor cursor = table.order(table.getPrimaryKeyIndexName());
if (!cursor.eof()) {
do {
getInitData(cursor);
} while (cursor.next());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
db.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
Does anybody know what's wrong with the issue? Due to this list, the actuall library usage was improper, but I've checked it out and there wasn't anything wrong to me. http://grepcode.com/file/repo1.maven.org/maven2/org.tmatesoft.sqljet/sqljet/1.0.2/org/tmatesoft/sqljet/core/SqlJetErrorCode.java#SqlJetErrorCode
Thanks!
It happens because you are trying to open a DB that is already opened by another process .
it happened to me because the db was opened by Firefox SQLite Manager, but basically it could happen by any other thread or process accessing your DB .
I am getting a
org.hibernate.TransactionException: nested transactions not supported
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1395)
at com.mcruiseon.server.hibernate.ReadOnlyOperations.flush(ReadOnlyOperations.java:118)
Code that throws that exception. I am calling flush from a thread that runs infinite until there is data to flush.
public void flush(Object dataStore) throws DidNotSaveRequestSomeRandomError {
Transaction txD;
Session session;
session = currentSession();
// Below Line 118
txD = session.beginTransaction();
txD.begin() ;
session.saveOrUpdate(dataStore);
try {
txD.commit();
while(!txD.wasCommitted()) ;
} catch (ConstraintViolationException e) {
txD.rollback() ;
throw new DidNotSaveRequestSomeRandomError(dataStore, feedbackManager);
} catch (TransactionException e) {
txD.rollback() ;
} finally {
// session.flush();
txD = null;
session.close();
}
// mySession.clear();
}
Edit :
I am calling flush in a independent thread as datastore list contains data. From what I see its a sync operation call to flush, so ideally flush should not return until transaction is complete. I would like it that way is the least I want to expect. Since its a independent thread doing its job, all I care about it flush being a sync operation. Now my question is, is txD.commit a async operation ? Does it return before that transaction has a chance to finish. If yes, is there a way to get commit to "Wait" until the transaction completes ?
public void run() {
Object dataStore = null;
while (true) {
try {
synchronized (flushQ) {
if (flushQ.isEmpty())
flushQ.wait();
if (flushQ.isEmpty()) {
continue;
}
dataStore = flushQ.removeFirst();
if (dataStore == null) {
continue;
}
}
try {
flush(dataStore);
} catch (DidNotSaveRequestSomeRandomError e) {
e.printStackTrace();
log.fatal(e);
}
} catch (HibernateException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Edit 2 : Added while(!txD.wasCommitted()) ; (in code above), still I get that freaking nested transactions not supported. Infact due to this exception a record is not being written to by table too. Is there something to do with the type of table ? I have INNODB for all my tables?
Finally got the nested transaction not supported error fixed. Changes made to code are
if (session.getTransaction() != null
&& session.getTransaction().isActive()) {
txD = session.getTransaction();
} else {
txD = session.beginTransaction();
}
//txD = session.beginTransaction();
// txD.begin() ;
session.saveOrUpdate(dataStore);
try {
txD.commit();
while (!txD.wasCommitted())
;
}
Credits of above code also to Venkat. I did not find HbTransaction, so just used getTransaction and beginTransaction. It worked.
I also made changes in the hibernate properties due to advice on here. I added these lines to the hibernate.properties. This alone did not solve the issue. But I am leaving it there.
hsqldb.write_delay_millis=0
shutdown=true
You probably already began a transaction before calling this method.
Either this should be part of the enclosing transaction, and you should thus not start another one; or it shouldn't be part of the enclosing transaction, and you should thus open a new session and a new transaction rather than using the current session.
I am trying to connect to my website's MySQL database, and I have no knowledge of PHP so I decided to use JDBC. I followed some video tutorials (non JDBC) and I used their steps. I skipped the MAMP step though because I am not hosting the server off of my PC. It is being hosted locally because it is going to be a larger website.
So I have this code entered in my Login Activity (first screen you see):
Connection connection = null;
Statement statement = null;
String username = "username";
String password = "password";
String dbURL = "jdbc:mysql://216.26.176.52:3306/lifesizefoto";
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(dbURL, username, password);
statement = connection.createStatement();
System.out.println("Connected.");
} catch (ClassNotFoundException error) {
System.out.println("Cannot connect");
} catch (SQLException error) {
System.out.println("Error: " + error.getMessage());
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (connection != null) { try {connection.close();} catch (SQLException ignore) {} }
if (statement != null) { try {statement.close();} catch (SQLException ignore) {} }
}
I have tried many variations to the .getConnection() statement, but I can't figure it out. I have also contacted the website host and he took down all firewalls for my IP and even opened up a special port for the app.
When I run my app, I get this error:
01-09 18:59:32.769: I/System.out(14178): Error: Communications link failure
01-09 18:59:32.769: I/System.out(14178): The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
I would appreciate any help. Thank you in advanced!
Two thoughts:
It's unlikely that your web site's MySQL server is bound to an external interface - it's likely only listening on the localhost interface. Your hosting provider should be able to confirm / possibly fix that for you.
Trying to connect a mobile app directly to a server database is probably not going to work well in the long run - I'd suggest that you either figure out how to write a server-side app (for your mobile app to connect to) in PHP, or find another language that your host supports, and do it in that.