2015-05-27 13:13:19 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2015 ezivkoc
|
2013-05-28 19:29:24 +00:00
|
|
|
*
|
2011-07-13 17:53:17 +00:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
2013-05-28 19:29:24 +00:00
|
|
|
*
|
2011-07-13 17:53:17 +00:00
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
|
* all copies or substantial portions of the Software.
|
2013-05-28 19:29:24 +00:00
|
|
|
*
|
2011-07-13 17:53:17 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
* THE SOFTWARE.
|
2015-05-27 13:13:19 +00:00
|
|
|
*/
|
2013-05-28 19:29:24 +00:00
|
|
|
|
2010-04-15 20:52:34 +00:00
|
|
|
package zutil.db;
|
|
|
|
|
|
2015-06-02 15:47:44 +00:00
|
|
|
import zutil.db.handler.SimpleSQLHandler;
|
|
|
|
|
import zutil.log.LogUtil;
|
2010-04-15 20:52:34 +00:00
|
|
|
|
|
|
|
|
import javax.naming.InitialContext;
|
|
|
|
|
import javax.naming.NamingException;
|
|
|
|
|
import javax.sql.DataSource;
|
2015-06-02 15:47:44 +00:00
|
|
|
import java.io.Closeable;
|
|
|
|
|
import java.math.BigInteger;
|
|
|
|
|
import java.sql.*;
|
|
|
|
|
import java.util.logging.Level;
|
|
|
|
|
import java.util.logging.Logger;
|
2011-01-21 18:34:23 +00:00
|
|
|
|
2011-09-14 17:02:06 +00:00
|
|
|
public class DBConnection implements Closeable{
|
2011-03-19 23:04:41 +00:00
|
|
|
private static final Logger logger = LogUtil.getLogger();
|
|
|
|
|
|
2010-04-15 20:52:34 +00:00
|
|
|
public enum DBMS{
|
2014-07-01 19:54:30 +00:00
|
|
|
MySQL,
|
|
|
|
|
SQLite
|
2010-04-15 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
// The connection
|
|
|
|
|
private Connection conn = null;
|
|
|
|
|
// The pool that this connection belongs to
|
|
|
|
|
private DBConnectionPool pool;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates an Connection from JNDI
|
|
|
|
|
*
|
|
|
|
|
* @param jndi the name of the connection, e.g. "jdbc/mysql"
|
|
|
|
|
*/
|
|
|
|
|
public DBConnection(String jndi) throws NamingException, SQLException{
|
|
|
|
|
InitialContext ctx = new InitialContext();
|
|
|
|
|
DataSource ds = (DataSource)ctx.lookup("java:comp/env/"+jndi);
|
|
|
|
|
conn = ds.getConnection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates an Connection to a MySQL server
|
|
|
|
|
*
|
|
|
|
|
* @param url is the URL of the MySQL server
|
|
|
|
|
* @param db is the database to connect to
|
|
|
|
|
* @param user is the user name
|
|
|
|
|
* @param password is the password
|
|
|
|
|
*/
|
|
|
|
|
public DBConnection(String url, String db, String user, String password) throws Exception{
|
|
|
|
|
this(DBMS.MySQL, url, db, user, password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates an Connection to a DB server
|
|
|
|
|
*
|
|
|
|
|
* @param dbms is the DB type
|
|
|
|
|
* @param url is the URL of the MySQL server
|
|
|
|
|
* @param db is the database to connect to
|
|
|
|
|
* @param user is the user name
|
|
|
|
|
* @param password is the password
|
|
|
|
|
*/
|
|
|
|
|
public DBConnection(DBMS dbms, String url, String db, String user, String password) throws Exception{
|
|
|
|
|
String dbms_name = initDriver(dbms);
|
|
|
|
|
conn = DriverManager.getConnection ("jdbc:"+dbms_name+"://"+url+"/"+db, user, password);
|
|
|
|
|
}
|
2014-07-01 19:54:30 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates an Connection to a DB file
|
|
|
|
|
*
|
|
|
|
|
* @param dbms is the DB type
|
|
|
|
|
* @param db is the database to connect to
|
|
|
|
|
*/
|
|
|
|
|
public DBConnection(DBMS dbms, String db) throws Exception{
|
|
|
|
|
String dbms_name = initDriver(dbms);
|
|
|
|
|
conn = DriverManager.getConnection ("jdbc:"+dbms_name+":"+db);
|
|
|
|
|
}
|
2010-04-15 20:52:34 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return the underlying connection
|
|
|
|
|
*/
|
|
|
|
|
public Connection getConnection(){
|
|
|
|
|
return conn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initiates the DB driver and returns its protocol name.
|
|
|
|
|
*
|
|
|
|
|
* @param db is the DB type
|
|
|
|
|
* @return the protocol name of the DBMS
|
|
|
|
|
*/
|
|
|
|
|
public String initDriver(DBMS db) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
|
|
|
|
|
switch(db){
|
|
|
|
|
case MySQL:
|
2014-07-01 19:54:30 +00:00
|
|
|
Class.forName("com.mysql.jdbc.Driver").newInstance();
|
2010-04-15 20:52:34 +00:00
|
|
|
DriverManager.setLoginTimeout(10);
|
|
|
|
|
return "mysql";
|
2014-07-01 19:54:30 +00:00
|
|
|
case SQLite:
|
|
|
|
|
Class.forName("org.sqlite.JDBC");
|
|
|
|
|
return "sqlite";
|
|
|
|
|
default:
|
|
|
|
|
return null;
|
2010-04-15 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return the last inserted id or -1 if there was an error
|
|
|
|
|
*/
|
2013-09-07 01:14:18 +00:00
|
|
|
public long getLastInsertID(){
|
2010-04-15 20:52:34 +00:00
|
|
|
try{
|
2013-09-07 01:14:18 +00:00
|
|
|
return exec("SELECT LAST_INSERT_ID()", new SimpleSQLHandler<BigInteger>()).longValue();
|
2010-05-18 20:36:44 +00:00
|
|
|
}catch(SQLException e){
|
2011-03-19 23:04:41 +00:00
|
|
|
logger.log(Level.WARNING, null, e);
|
|
|
|
|
}
|
2013-09-07 01:14:18 +00:00
|
|
|
return -1;
|
2010-04-15 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Runs a Prepared Statement.<br>
|
|
|
|
|
* <b>NOTE:</b> Don't forget to close the PreparedStatement or it can lead to memory leaks
|
|
|
|
|
*
|
|
|
|
|
* @param sql is the SQL query to run
|
|
|
|
|
* @return An PreparedStatement
|
|
|
|
|
*/
|
|
|
|
|
public PreparedStatement getPreparedStatement(String sql) throws SQLException{
|
|
|
|
|
return conn.prepareStatement(sql);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <b>NOTE:</b> Don't forget to close the Statement or it can lead to memory leaks
|
|
|
|
|
*
|
|
|
|
|
* @return an Statement for the DB
|
|
|
|
|
*/
|
|
|
|
|
public Statement getStatement() throws SQLException{
|
|
|
|
|
return conn.createStatement();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Executes an query and cleans up after itself.
|
|
|
|
|
*
|
|
|
|
|
* @param query is the query
|
|
|
|
|
* @return update count or -1 if the query is not an update query
|
|
|
|
|
*/
|
|
|
|
|
public int exec(String query) throws SQLException {
|
|
|
|
|
PreparedStatement stmt = getPreparedStatement( query );
|
|
|
|
|
return exec(stmt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Executes an query and cleans up after itself.
|
|
|
|
|
*
|
|
|
|
|
* @param stmt is the query
|
|
|
|
|
* @return update count or -1 if the query is not an update query
|
|
|
|
|
*/
|
|
|
|
|
public static int exec(PreparedStatement stmt) throws SQLException {
|
2014-07-01 19:54:30 +00:00
|
|
|
Integer ret = exec(stmt, new SQLResultHandler<Integer>(){
|
2010-10-07 11:27:23 +00:00
|
|
|
public Integer handleQueryResult(Statement stmt, ResultSet result) {
|
2010-04-15 20:52:34 +00:00
|
|
|
try {
|
2014-07-01 19:54:30 +00:00
|
|
|
if(stmt != null)
|
|
|
|
|
return stmt.getUpdateCount();
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
2010-04-15 20:52:34 +00:00
|
|
|
} catch (SQLException e) {
|
2011-03-19 23:04:41 +00:00
|
|
|
logger.log(Level.WARNING, null, e);
|
2010-04-15 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
});
|
2014-07-01 19:54:30 +00:00
|
|
|
|
|
|
|
|
if(ret != null)
|
|
|
|
|
return ret;
|
|
|
|
|
return -1;
|
2010-04-15 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Executes an query and cleans up after itself.
|
|
|
|
|
* @param <T>
|
|
|
|
|
*
|
|
|
|
|
* @param query is the query
|
|
|
|
|
* @param handler is the result handler
|
|
|
|
|
* @return update count or -1 if the query is not an update query
|
|
|
|
|
*/
|
|
|
|
|
public <T> T exec(String query, SQLResultHandler<T> handler) throws SQLException {
|
|
|
|
|
PreparedStatement stmt = getPreparedStatement( query );
|
|
|
|
|
return exec(stmt, handler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Executes an query and cleans up after itself.
|
|
|
|
|
*
|
|
|
|
|
* @param stmt is the query
|
|
|
|
|
* @param handler is the result handler
|
|
|
|
|
* @return the object from the handler
|
|
|
|
|
*/
|
|
|
|
|
public static <T> T exec(PreparedStatement stmt, SQLResultHandler<T> handler) throws SQLException{
|
|
|
|
|
try{
|
|
|
|
|
// Execute
|
|
|
|
|
stmt.execute();
|
|
|
|
|
|
|
|
|
|
// Handle result
|
|
|
|
|
if( handler != null ){
|
|
|
|
|
ResultSet result = null;
|
|
|
|
|
try{
|
2014-07-01 19:54:30 +00:00
|
|
|
if(stmt.getMoreResults()){
|
|
|
|
|
result = stmt.getResultSet();
|
|
|
|
|
return handler.handleQueryResult(stmt, result);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return null;
|
|
|
|
|
}catch(SQLException sqlex){
|
|
|
|
|
logger.throwing(null, null, sqlex);
|
2010-04-15 20:52:34 +00:00
|
|
|
}finally{
|
|
|
|
|
if(result != null){
|
|
|
|
|
try {
|
|
|
|
|
result.close();
|
2014-07-01 19:54:30 +00:00
|
|
|
} catch (SQLException sqlex) {
|
|
|
|
|
logger.throwing(null, null, sqlex);
|
|
|
|
|
}
|
2010-04-15 20:52:34 +00:00
|
|
|
result = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-07-01 19:54:30 +00:00
|
|
|
}catch(SQLException sqlex){
|
|
|
|
|
logger.throwing(null, null, sqlex);
|
2010-04-15 20:52:34 +00:00
|
|
|
// Cleanup
|
|
|
|
|
} finally {
|
|
|
|
|
if (stmt != null) {
|
|
|
|
|
try {
|
|
|
|
|
stmt.close();
|
2014-07-01 19:54:30 +00:00
|
|
|
} catch (SQLException sqlex) {
|
|
|
|
|
logger.throwing(null, null, sqlex);
|
|
|
|
|
}
|
2010-04-15 20:52:34 +00:00
|
|
|
stmt = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the pool that this connection belongs to
|
|
|
|
|
*
|
|
|
|
|
* @param pool is the pool
|
|
|
|
|
*/
|
|
|
|
|
protected void setPool(DBConnectionPool pool){
|
|
|
|
|
if( pool != null )
|
|
|
|
|
pool.removeConnection(this);
|
|
|
|
|
this.pool = pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if the DB Connection is valid and functioning
|
|
|
|
|
*
|
|
|
|
|
* @return true or false depending on the validity of the connection
|
|
|
|
|
*/
|
|
|
|
|
public boolean valid(){
|
|
|
|
|
try {
|
|
|
|
|
conn.getMetaData();
|
2010-05-18 20:36:44 +00:00
|
|
|
return !conn.isClosed();
|
2010-04-15 20:52:34 +00:00
|
|
|
}catch (Exception e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Disconnects from the database or releases the connection back to the pool
|
|
|
|
|
*/
|
2010-05-18 20:36:44 +00:00
|
|
|
public void close(){
|
2010-04-15 20:52:34 +00:00
|
|
|
if(pool!=null){
|
|
|
|
|
pool.releaseConnection(this);
|
2010-05-18 20:36:44 +00:00
|
|
|
conn = null;
|
2010-04-15 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
forceClose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Disconnects from the database
|
|
|
|
|
*/
|
|
|
|
|
public void forceClose(){
|
|
|
|
|
if (conn != null) {
|
|
|
|
|
try {
|
2011-03-27 20:01:36 +00:00
|
|
|
if( !conn.isClosed() )
|
2011-03-19 23:04:41 +00:00
|
|
|
conn.close();
|
|
|
|
|
} catch (SQLException e) {
|
|
|
|
|
logger.log(Level.WARNING, null, e);
|
2010-04-15 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
conn = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean equals(Object o){
|
|
|
|
|
return conn.equals(o);
|
|
|
|
|
}
|
|
|
|
|
}
|