#java #sql #connection-pooling
#java #sql #объединение в пул соединений
Вопрос:
У меня проблема с ConnectionPool, которая очень быстро исчерпывается. По сути, я загрузил прослушиватель в приложение, всякий раз, когда контекст инициализируется, запускается таймер, и timertask внутри него будет выполнять SQL-запрос, который использует пул соединений «jar пула соединений, который я скопировал в Tomcat 6» Слушатель «только соответствующий метод»:
private MyTask task=new MyTask();
public void contextInitialized(ServletContextEvent event) {
this.ctx=event.getServletContext();
Timer timer= new Timer();
Calendar calendar=Calendar.getInstance();
Date firstTime=calendar.getTime();
timer.scheduleAtFixedRate(task, firstTime, 1000*60);
ctx.setAttribute("timer",timer);
}
The connection pool:
public class ConnectionPool {
private static ConnectionPool pool=null;
private static DataSource source=null;
/**
* Private constructor
* Private omdat dit klasse een singleton-patroon volgd, dus nooit meer dan een instantie is toegestaan.
*/
private ConnectionPool(){
try{
InitialContext ini=new InitialContext();
source=(DataSource)ini.lookup("java:/comp/env/jdbc/verkocht");
}catch(Exception e){
System.out.println("Verkocht db not found");//bedoelt voor test
e.printStackTrace();
}
}
/**
* Singleton getInstance() methode
* @return the connection pool
*/
public static ConnectionPool getInstance(){
if(pool==null){
pool=new ConnectionPool();
}
return pool;
}
/**
* Deze methode returneert een Connection instantie uit het pool
* @return the Connection
*/
public Connection getConnection(){
try{
return source.getConnection();
}catch(SQLException e){
System.out.println("No connection estabilished");
e.printStackTrace();
return null;
}
}
/**
* Sluid deze Connection object
* @param Een connection instantie
*/
public void freeConnection(Connection c){
try{
c.close();
} catch(SQLException e){
e.printStackTrace();
}
}
public static void main(String[] args){
ConnectionPool con=ConnectionPool.getInstance();
con.getConnection();
}
}
По сути, я получаю нулевой указатель в этой строке:
return source.getConnection();
Сообщая мне, что имя базы данных не найдено.
Проблема в том, что он работает в первый раз, в течение 5 или 6 минут (когда я устанавливаю таймер на 1000 * 60) запросы отправляются успешно, поэтому база данных найдена, что означает, что конфигурация в context.xml это правильно.
Метод, который использует пул соединений изнутри переопределенного метода run MyTask, который расширяет TimerTask, является:
public void assign(int toegewezenAan, double verkoopPrijs, double totaalAfgetrokken, int artikelId){
String sqlUpdate="UPDATE artikelen SET toegewezenAan=?, verkoopPrijs=?, totaalAfgetrokken=?, status=? WHERE artikelId=?";
ConnectionPool pool=ConnectionPool.getInstance();
Connection con=pool.getConnection();
PreparedStatement prep=null;
try{
prep=con.prepareStatement(sqlUpdate);
prep.setInt(1,toegewezenAan);
prep.setDouble(2, verkoopPrijs);
prep.setDouble(3,totaalAfgetrokken);
prep.setString(4, "VERKOCHT");
prep.setInt(5, artikelId);
prep.executeUpdate();
} catch(SQLException e){
e.printStackTrace();
pool.freeConnection(con);
}
}
Любой совет?
Ответ №1:
Вы освобождаете соединение только в catch-блоке, но на самом деле вам нужно освобождать его каждый раз.
Вы должны поместить его в блок finally, чтобы соединение освобождалось (и возвращалось в пул) после каждого использования.
ConnectionPool pool=ConnectionPool.getInstance();
Connection con=pool.getConnection();
PreparedStatement prep=null;
try{
prep=con.prepareStatement(sqlUpdate);
prep.setInt(1,toegewezenAan);
prep.setDouble(2, verkoopPrijs);
prep.setDouble(3,totaalAfgetrokken);
prep.setString(4, "VERKOCHT");
prep.setInt(5, artikelId);
prep.executeUpdate();
} catch(SQLException e){
e.printStackTrace();
} finally
{
pool.freeConnection(con);
}
И вы должны вызвать prep.close()
finally, чтобы закрыть PreparedStatement (если pool.freeConnection(con)
не принимает это само по себе)).