2016-04-18 10 views
1

私のサーバーにMySqlデータベースのレコードを記録するアプリケーションで作業しています。データベースを使用するたびに既存の接続を取得し、そうでない場合は初めてと思います。私がインサートをしたり選択したりするのは非常にうまくいくが、その相談に続いて、それが終わったときに私は決してつながりを取り戻すことができず、相談に戻らない。データベースのオープンとクローズ

データベース

public class Database { 
/** 
* Gets just one instance of the class 
* Connects on construct 
* @returns connection 
*/ 
private Connection _conn = null; 
private long timer; 

//singleton code 
private static Database DatabaseObject; 
private Database() {} 
public static Database connect() { 
    if (DatabaseObject == null) 
     DatabaseObject = new Database(); 
    return DatabaseObject._connect(); 
} 
public Object clone() throws CloneNotSupportedException { 
    throw new CloneNotSupportedException(); 
} 
//end singleton code 


/** 
* Connects with the defined parameters on Config 
* Prevents re-connection if object was already connected 
* @throws SQLException 
*/ 
private Database _connect() { 
    try { 
    if (this._conn == null || !this._conn.isValid(0)) { 
     try { 
      Class.forName("com.mysql.jdbc.Driver"); 
      Properties connProps = new Properties(); 
      connProps.put("user", Config.Config.DB_USER); 
      connProps.put("password", Config.Config.DB_PASS); 
      this._conn = DriverManager. 
         getConnection("jdbc:" + Config.Config.DB_DBMS + "://" + Config.Config.DB_HOST + ":" 
           + Config.Config.DB_PORT + "/" + Config.Config.DB_NAME, Config.Config.DB_USER, Config.Config.DB_PASS); 
      timer = System.currentTimeMillis(); 
     } catch (ClassNotFoundException e) { 
      System.out.println("Where is your MySQL JDBC Driver?"); 
      e.printStackTrace(); 
     } catch (Exception e) { 
      System.out.println("Could not connect to DB"); 
      e.printStackTrace(); 
     } 
    } else { 
     try { 
      long tmp = System.currentTimeMillis() - timer; 
      if (tmp > 1200000) { //3600000 one hour ; 1200000 twenty minutes 
       System.out.println("Forcing reconnection ("+tmp+" milliseconds passed since last connection)"); 
       this.close(); 
       this._connect(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.out.println("Forcing reconnection"); 
      this._conn = null; 
      this._connect(); 
     } 
    } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return this; 
} 

/** 
* Closes connections 
* This has to be invoked when database connection is no longer needed 
* @throws SQLException 
*/ 
public void close() throws SQLException { 
    if (this._conn != null) { 
     this._conn.close(); 
     this._conn = null; 
    } 
} 

    /** 
    * Getter for connection 
    * @return 
    */ 
    public Connection get() { 
     return this._conn; 
    } 
} 

私は、クエリにする次の関数の私のクラス:

private Statement sment = null; 
private PreparedStatement psment = null; 
private ResultSet rset = null; 
public boolean existsByNameAndUserId(String md5, int userId, int eventId) { 
    Connection conn = Database.connect().get(); 
    try { 
     psment = conn.prepareStatement("SELECT * FROM files " 
             + "WHERE user_id = ? AND md5 = ? AND evento_id = ?"); 
     psment.setInt(1, userId); 
     psment.setString(2, md5); 
     psment.setInt(3, eventId); 
     rset = psment.executeQuery(); 

     if (rset.next()) { 
      return true; 
     } 
    } catch (Exception e) { 

     e.printStackTrace(); 
    } 

    return false; 
} 

private void close() { 
    try { if (rset != null) rset.close(); } catch (Exception e) {System.out.println(e.getMessage());}; 
    try { if (psment != null) psment.close(); } catch (Exception e) {System.out.println(e.getMessage());}; 
    try { if (sment != null) sment.close(); } catch (Exception e) {System.out.println(e.getMessage());}; 
} 

をし、次の中で、私はこれらを持つレコードかどうかを調べるために上記の関数を呼び出します特性、そうでなければ、私は挿入を行います。

String SQL_INSERT = "INSERT INTO files (evento_id, user_id, path, thumb, preview, width, height, md5, numero_corredor, created, modified) " 
     + "VALUES (?,?,?,?,?,?,?,?,?,NOW(),NOW())"; 
public void save(List<components.File.Schema> files) throws SQLException { 
    try (
      Connection conn = Database.connect().get(); 
      PreparedStatement statement = conn.prepareStatement(SQL_INSERT); 
     ) { 
      int i = 0; 

      for (components.File.Schema file : files) { 
       if(!existsByNameAndUserId(file.getMd5(), file.getUserId(), file.getEventId())){ 
        statement.setInt(1, file.getEventId()); 
        statement.setInt(2, file.getUserId()); 
        statement.setString(3, file.getPath()); 
        statement.setString(4, file.getPreview()); 
        statement.setString(5, file.getThumb()); 

        statement.setInt(6, file.getWidth()); 
        statement.setInt(7, file.getHeight()); 
        statement.setString(8, file.getMd5()); 
        statement.setString(9, null); 
        statement.addBatch(); 
        i++; 
        if (i % 1000 == 0 || i == files.size()) { 
         statement.executeBatch(); // Execute every 1000 items. 
        } 
       } 
      } 
     } 
} 
+0

チェックしてください - http://stackoverflow.com/help/mcve – Razib

+0

コードを提供し、可能な限り説明できるようにしようとしていますが、理解できませんか?私はより多くのコードを書いて追加しようとします。 @Razib – hateful

+0

いいえ、私の意見では、最も良い質問は簡潔で分かりやすいものです。 – Razib

答えて

1

あなたの問題はあなたが行うことになっているものですが、それはあなたの接続とするとき、あなたが持っていない_connect()方法として、再びそれを呼び出すを閉じtry-with-resources文でConnection conn = Database.connect().get()を置くという事実によるものです有効なテストでは、新しい接続を作成しません。有効なテストはthis._conn == null || !this._conn.isValid(0)です。元のテストでは実際にthis._conn.isValid(0)と呼ばれており、接続が閉じられているので、falseが返されますので、ここでは望んでいない新しい接続が作成されることはありません。

レスポンス更新:保存methodにあなたは現在の接続を閉じたexistsByNameAndUserIdを呼び出すこと問題の2番目の部分は事実であり、あなただけの文を閉じる必要がありますし、この方法は、接続を閉じ、保存しましょう。

+0

こんにちは、お返事ありがとうございます。このメソッドでは、データベースを閉じずに私のポストコードでeditareと失敗するので、メソッドコードclose()を追加したくないと思います。 – hateful

+1

ConnectionがAutoCloseableとして閉じるメソッドを追加する必要はありませんしたがって、リソース付き試行文のコンテキスト内ですでに呼び出されています –

+0

私はあなたが言ったように接続を検証するために自分のコードを理解して変更しますが、それと同じように動作します。データベースの最初の相談で、私は再びアクセスすることはできません。 – hateful

関連する問題