(EDITED)
I am using the following code to check if my Postgres db is up and running. However if the machine running the db is slow (Not enough RAM for example) it sometimes pass but when i tried to get some real data from the db (a few millisec after) i fail. I guess because not all tables were loaded.
Here is my code:
public static boolean testDBConnection(boolean refreshFactory) throws Exception
Session session = null;
try {
if(refreshFactory){
ConnectionUtil.refreshSessionFactory();
}
session = ConnectionUtil.getSessionFactory().openSession();
String sql = "select 1";
session.createSQLQuery(sql).list();
return true;
}
catch (HibernateException e) {
String error = "Failed to connect db.";
throw ExceptionFactory.create(error);
}
finally{
if(session!=null){
session.close();
}
}
}
Is there a better way then "select 1"?
Thanks
Related
I am using MS SQL Server, and my program recently started losing the DB connection randomly. I am using a non-XA driver.
The most likely suspect is the asynchronous database logging I added.
The sneaky thing is, I have used a thread pool:
ExecutorService ruleLoggingExecutor = Executors.newFixedThreadPool(10);
and in the finally block of my process, I start off a new thread that calls down to the addLogs() method.
The code works for hours, days, and then during a totally unrelated query, it will lose the DB connection. I have an inkling that the problem is that two concurrent inserts are being attempted. But I don't know if putting 'synchronized' on the addLogs method would fix it, or if I need transactional code, or what. Any advice?
In the DAO:
private EntityManager getEntityManager(InitialContext context) {
try {
if (emf == null) {
emf = (EntityManagerFactory) context
.lookup("java:jboss/persistence/db");
}
return emf.createEntityManager();
} catch (Exception e) {
logger.error(
"Error finding EntityManagerFactory in JNDI: "
+ e.getMessage(), e);
return null;
}
}
public void addLogs(InitialContext context, String key, String logs,
String responseXml) {
EntityManager em = getEntityManager(context);
try {
TblRuleLog log = new TblRuleLog();
log.setAuthKey(key);
log.setLogMessage(logs);
log.setDateTime(new Timestamp(new Date().getTime()));
log.setResponseXml(responseXml);
em.persist(log);
em.flush();
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
em.close();
}
}
It seems the connection is closed after a timeout, perhaps due to transaction not being commited/rolled back (and locks not being released on the tables/rows).
Manual flushing looks suspicious. I'd use entityManager.getTransaction().begin/commit() and remove em.flush().
I have a Java application where I want to be able to kill queries made to several databases. I know how to get the queries in the information_schema.processlist, but the problem is I don't know how to kill those queries. Usually I would do it using KILL command, but I cant use it in java application (or at least I havent figured out how to do it).
I've been reading about the Statement.cancel but the problem is that the queries are created by another application. I've understood that you have to have Statement variable in the class where you want to cancel it.
if I can use Statement for this purpose, can someone please help me to understand how. I'm using MySQL database. I dont want to set timeout, because I want to be able to kill any query I want to.
These are some examples how I've tried to kill the process:
public synchronized void killProcesses(Set<Long> ids) {
for (long id : ids) {
String killCommand="Select 'KILL ' from processlist where id=:id";
Query query= queryManager.createQuery(killCommand);
query.setParameter("id", id);
query.getResultList();
}
}
public synchronized void killProcesses(Set<Long> ids) {
for (long id : ids) {
String killCommand="KILL " + id;
Query query= queryManager.createQuery(killCommand);
query.getResultList();
}
}
#HannoBinder solved the problem, the final solution is:
private String killQuery(long id) {
String killCommand="KILL " + id;
queryManager.getTransaction().begin();
Query query=queryManager.createNativeQuery(killCommand);
query.executeUpdate();
queryManager.getTransaction().commit();
return "OK";
}
And one that worked too, but isnt that simple:
public synchronized void killProcesses(Set<Long> ids) {
for (long id : ids) {
String killCommand="KILL QUERY " + id;
queryManager.getTransaction().begin();
Connection conn=queryManager.unwrap(Connection.class);
try {
Statement statement= conn.createStatement();
statement.execute(killCommand);
} catch (SQLException e) {
e.printStackTrace();
} finally {
queryManager.getTransaction().commit();
conn.close();
}
}
}
My question is about hibernate, actually I'm working on a Java EE application using hibernate and mysq.
Everything looks fine. but I still have one problem when I insert data via phpMyAdmin to my database, I cannot access them immediately via hibernate unless I started the server (tomcat) again.
This is because your transaction in phpMyAdmin was not committed.
Try running this query in phpMyAdmin before running commands.
SET ##AUTOCOMMIT = 1;
Or running commit; at the end of your query.
Possible duplicate of:
COMMIT not working in phpmyadmin (MySQL)
I noticed that i've forgot to add transaction.commit(); for every hibernate session.get(); method, so somehow it keeps data in the cache.
public List<User> getAllUsers(User user) throws Exception {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Criteria c = session.createCriteria(User.class).add(Restrictions.ne("idUser", user.getIdUser()));
List<User> users = c.list();
tx.commit();//i forget to add this
return users;
} catch (Exception e) {
if (tx != null) tx.rollback(); throw e;
} finally {
session.close();
}
}
I'm working on a webapp where i manually create my DataSource. (also see my other question why: How to use Spring to manage connection to multiple databases) because I need to connect to other databases (dev, prod, qa, test).
Now I have solved it to choose and switch between databases. But if a user logs out of my app. He wants to try to connect to an other database. He is still connected to the same datasource because at runtime the myDs is not null. How can I properly dispose of this Datasource when user logs out? I don't want the user to create the datasource every time he queries the database.
private DataSource createDataSource(Environment e) {
OracleDataSource ds = null;
String url = null;
try {
if (myDs != null) {
logger.info("myDs connection: " + etmetaDs.getConnection().getMetaData().getURL());
url = myDs.getConnection().getMetaData().getURL();
}
} catch (SQLException exc) {
// TODO Auto-generated catch block
exc.printStackTrace();
}
if (myDs == null) {
try {
ds = new OracleDataSource();
} catch (SQLException ex) {
ex.printStackTrace();
}
ds.setDriverType("oracle.jdbc.OracleDriver");
ds.setURL(e.getUrl());
try {
Cryptographer c = new Cryptographer();
ds.setUser(c.decrypt(e.getUsername()));
ds.setPassword(c.decrypt(e.getPassword()));
} catch (CryptographyException ex) {
logger.error("Failed to connect to my environment [" + e.getName() + "]");
ex.printStackTrace();
return null;
}
logger.info("Connecting to my environment [" + e.getName() + "]");
myDs = ds;
} else if (url.equals(e.getUrl())) {
} else {
}
return myDs;
}
If you read the answer of Reza in you other question you can see how to create multiple DataSource.
I think here that the problem is not the DataSource but the way you store information in your code. I suppose that your etmetaDs is shared but all your users, so dispose it when a user log out (= set it to null) is not the good option.
What you have to do, is to maintain the status of the connection for each user. And when a user log off, you can reset is status in order to obtain a new connection the next time it connects.
Update: There are many way to achieve this. I give here an example of what I imagine, but you have to adapt it to your needs. Suppose that you have a UserData object that holds information :
public class UserData
{
String id;
String name;
String database;
}
You may have in your application a dropdown with the name of the database (dev, test, ...) with an empty first item. When the user selects a database, you get the connection with createDataSource(). If it already exists you returns the DataSource else you create a new one. When your user disconnect (or when the user log on), you set the database to "" to force him to select the database in the dropdown. There is no need to reset the datasource.
I'm trying to access a MS_Access db using StelsMDB library. The file is on the SD card of the phone. I loaded all libraries, created the connection:
public class DBConnection {
private static final String TAG = DBConnection.class.getSimpleName();
private Connection connection;
public DBConnection() {
try {
Class.forName(jstels.jdbc.mdb.MDBDriver2.class.getName());
connection = DriverManager.getConnection("jdbc:jstels:mdb:sdcard/2012xp.mdb");
} catch (SQLException e) {
Log.e(TAG, "", e);
} catch (ClassNotFoundException e1) {
Log.e(TAG, "", e1);
}
}
public Connection getConnection() {
return this.connection;
}
}
and it seems to work; but when i try to query something i get the following exception:
Failed parsing query
java.lang.IllegalStateException: unknown query object flag 3
Online i can't find any hint. I get this exception with a complex query, so i tryied to write an easier one like
"SELECT * FROM TABLE_NAME"
....but i get the same exception.
I belive you have a mistake in the connection string. You need to creat Connection object with it's atributes.
Try replacing your connection with this:
Connection conn = DriverManager.getConnection("jdbc:jstels:mdb:sdcard/2012xp.mdb");
After a long trying i found out that jStels is not compatible with android...