2016-05-01 15 views
0

Ich versuche, ein Verbindungspooling zu implementieren, um eine Multithread-Anwendung zu haben (aber ohne UOW).org.apache.commons.dbcp2.DelegatingPreparedStatement mit Adresse: "NULL" ist geschlossen

Ich habe jedes Mal das gleiche Problem, wenn ich versuche, Methoden nach dem Login aufzurufen.

Ich habe diesen Fehler: org.apache.commons.dbcp2.DelegatingPreparedStatement mit der Adresse: "NULL" ist geschlossen.

Meine prepareStatements sind in einer Karte gespeichert, um wieder verwendet zu werden. Sie sind niemals geschlossen.

Klasse My Service:

public class ServicesImpl implements BackendServices, Services { 
private ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(); 
private ThreadLocal<String> connectionState = new ThreadLocal<String>(); 

public static final int TIMEOUT = 0; 

private String url = ""; 
private String usr = ""; 
private String pwd = ""; 


/** 
* Constructeur. 
* 
* @param url connexion 
* @param usr login 
* @param pwd mdp 
* @throws DALException 
*/ 
public ServicesImpl(String url, String usr, String pwd) { 
    this.url = url; 
    this.usr = usr; 
    this.pwd = pwd; 
    connectionState.set("Empty"); 
    openDataAccess(); 
} 

public ServicesImpl() { 

} 

/** 
* Méthode permettant de bloquer la table en BD. 
* 
* @throws DALException 
**/ 
@Override 
public void beginTransaction() { 
    try { 
    threadLocal.get().setAutoCommit(false); 
    } catch (SQLException e) { 
    throw new DALException(e.getMessage()); 
    } 
} 

/** 
* Méthode permettant de valider une transaction en BD. 
* 
* @throws DALException 
**/ 
@Override 
public void commit() { 
    try { 
    threadLocal.get().commit(); 
    threadLocal.get().setAutoCommit(true); 
    } catch (SQLException e) { 
    throw new DALException(e.getMessage()); 
    } 
} 

/** 
* Méthode permettant d'annuler une transaction en BD. 
* 
* @throws DALException 
**/ 
@Override 
public void rollback() { 
    try { 
    threadLocal.get().rollback(); 
    threadLocal.get().setAutoCommit(true); 
    } catch (SQLException e) { 
    throw new DALException(e.getMessage()); 
    } 
} 

/** 
* Méthode permettant d'ouvrir la connexion. 
* 
* @throws DALException 
* @throws SQLException 
* @throws ClassNotFoundException 
**/ 
@Override 
public void openDataAccess() { 
    try { 
    Class.forName("org.postgresql.Driver"); 
    try { 
     threadLocal.set(DataSource.getInstance().getConnection()); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (PropertyVetoException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    testConnection(); 
    } catch (SQLException e) { 
    e.printStackTrace(); 
    } catch (ClassNotFoundException e) { 
    throw new DALException(e.getMessage()); 
    } 
} 

/** 
* Méthode permettant de fermer la connexion. 
* 
* @throws DALException 
**/ 
@Override 
public void closeDataAccess() { 
    try { 
    testConnection(); 
    threadLocal.get().setAutoCommit(false); 
    threadLocal.get().rollback(); 
    threadLocal.get().close(); 
    threadLocal.remove(); 
    } catch (SQLException e) { 
    throw new DALException(e.getMessage()); 
    } 
} 

/** 
* Méthode permettant de tester si la connexion est libre. 
* 
* @throws DALException 
**/ 
private void testConnection() { 

    try { 
    if (!threadLocal.get().isValid(TIMEOUT)) { 
     throw new DALException("Connexion non valide !"); 
    } 
    } catch (SQLException e) { 
    throw new DALException(e.getMessage()); 
    } 

} 

/** 
* Méthode permettant de distribuer des PS sur la connexion. 
* 
* @param la requete 
* @return PreparedStatement 
* @throws DALException 
**/ 
@Override 
public PreparedStatement getPreparedStatement(String requete) { 
    try { 
    return threadLocal.get().prepareStatement(requete); 
    } catch (SQLException e) { 
    // throw new DALException(e.getMessage()); 
    e.printStackTrace(); 
    return null; 
    } 
} 


    public void openConnection(String query) { 
    if (connectionState.get() == null) { 
     connectionState.set("Empty"); 
    } 
    if (connectionState.get().equals("Empty")) { 
     connectionState.set(query); 
     try { 
     threadLocal.set(DataSource.getInstance().getConnection()); 
     } catch (SQLException | IOException | PropertyVetoException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     } 
     this.openDataAccess(); 
    } 
    } 

    @Override 
    public void closeConnection(String query) { 
    if (connectionState.get().equals(query)) { 
     connectionState.set("Empty"); 
     this.closeDataAccess(); 
    } 
    } 
} 

Es gibt eine exemple von DAO, um zu verstehen, wie es funktioniert:

public class DocumentDaoImpl implements DocumentDao { 

BackendServices bs; 
BizFactory fac; 
private ChoixMobiliteDao cmdao; 
private String schema; 

private Map<String, PreparedStatement> mapPs = new HashMap<String, PreparedStatement>(); 
private PreparedStatement ps; 

private enum ColonneDb { 
    ID, MOBILITE_ID, CONTRAT_BOURSE, CONVENTION_STAGE, CHARTE_ETUDIANT, PREUVE_TEST_LINGUISTIQUE_BEFORE, DOCUMENT_ENGAGEMENT, ATTESTATION_SEJOUR, RELEVE_NOTE, CERTIFICAT_STAGE, RAPPORT_FINAL, PREUVE_TEST_LINGUISTIQUE_AFTER 
} 

private String getDocument; 
private String getDocumentById; 
private String getDocumentsByMobilite; 
private String addDocument; 
private String updateDocument; 

/** 
* Constructeur 
* 
* @param dal 
* @param fac 
* @param ap 
* @param cmdao 
* @param tdao 
*/ 
public DocumentDaoImpl(Services dal, BizFactory fac, AppContext ap, ChoixMobiliteDao cmdao, 
    TypeDao tdao) { 
    this.bs = (BackendServices) dal; 
    this.schema = ap.getProperty("DocumentDAOSchema"); 
    this.fac = fac; 
    this.cmdao = cmdao; 

    String getDocument = "SELECT " + ColonneDb.ID + "," + ColonneDb.MOBILITE_ID + "," 
     + ColonneDb.CONTRAT_BOURSE + "," + ColonneDb.CONVENTION_STAGE + "," 
     + ColonneDb.CHARTE_ETUDIANT + "," + ColonneDb.PREUVE_TEST_LINGUISTIQUE_BEFORE + "," 
     + ColonneDb.DOCUMENT_ENGAGEMENT + "," + ColonneDb.ATTESTATION_SEJOUR + "," 
     + ColonneDb.RELEVE_NOTE + "," + ColonneDb.CERTIFICAT_STAGE + "," + ColonneDb.RAPPORT_FINAL 
     + "," + ColonneDb.PREUVE_TEST_LINGUISTIQUE_AFTER + " FROM " + schema + ""; 

    getDocumentById = getDocument + " WHERE " + ColonneDb.ID + " =?"; 
    getDocumentsByMobilite = getDocument + " WHERE " + ColonneDb.MOBILITE_ID + " =?"; 
    addDocument = "INSERT INTO " + schema + " VALUES (DEFAULT,?,?,?,?,?,?,?,?,?,?,?) returning " 
     + ColonneDb.ID; 
    updateDocument = 
     " UPDATE " + schema + " SET " + ColonneDb.MOBILITE_ID + " =? ," + ColonneDb.CONTRAT_BOURSE 
      + " =? ," + ColonneDb.CONVENTION_STAGE + " =? ," + ColonneDb.CHARTE_ETUDIANT + " =? ," 
      + ColonneDb.PREUVE_TEST_LINGUISTIQUE_BEFORE + " =? ," + ColonneDb.DOCUMENT_ENGAGEMENT 
      + " =? ," + ColonneDb.ATTESTATION_SEJOUR + " =? ," + ColonneDb.RELEVE_NOTE + " =? ," 
      + ColonneDb.CERTIFICAT_STAGE + " =? ," + ColonneDb.RAPPORT_FINAL + " =? ," 
      + ColonneDb.PREUVE_TEST_LINGUISTIQUE_AFTER + " =? WHERE " + ColonneDb.ID + " =?"; 

} 

/** 
* Méthode qui va chercher le DTO en DB et qui l'initialise 
* 
* @param rs 
* @return un DTO complété 
* @throws SQLException 
*/ 
public DocumentDto getDocumentDto(final ResultSet rs) throws SQLException { 
    DocumentDto result = fac.getDocumentDto(); 
    result.setId(rs.getInt(1)); 
    result.setChoixMobiliteDto(cmdao.getChoixMobiliteById(rs.getInt(2))); 
    result.setContratBourse(rs.getBoolean(3)); 
    result.setConventionStage(rs.getBoolean(4)); 
    result.setCharteEtudiant(rs.getBoolean(5)); 
    result.setPreuveTestLinguistiqueBefore(rs.getBoolean(6)); 
    result.setDocumentEngagement(rs.getBoolean(7)); 
    result.setAttestationSejour(rs.getBoolean(8)); 
    result.setReleveNote(rs.getBoolean(9)); 
    result.setCertificatStage(rs.getBoolean(10)); 
    result.setRapportFinal(rs.getBoolean(11)); 
    result.setPreuveTestLinguistiqueAfter(rs.getBoolean(12)); 

    return result; 
} 

@Override 
public DocumentDto getDocumentById(int id) { 
    DocumentDto areturn = null; 
    try { 
    mapPs.putIfAbsent("getDocumentById", bs.getPreparedStatement(getDocumentById)); 
    ps = mapPs.get("getDocumentById"); 
    ps.setInt(1, id); 
    try (ResultSet rs = ps.executeQuery()) { 
     if (!rs.next()) { 
     rs.close(); 
     return null; 
     } 
     areturn = this.getDocumentDto(rs); 
     return areturn; 
    } 
    } catch (final SQLException ex) { 
    throw new DALException(ex.getMessage()); 
    } 
} 

@Override 
public DocumentDto getDocumentsByMobilite(int id) { 
    try { 
    DocumentDto tmp = null; 
    mapPs.putIfAbsent("getDocumentsByMobilite", bs.getPreparedStatement(getDocumentsByMobilite)); 
    ps = mapPs.get("getDocumentsByMobilite"); 
    ps.setInt(1, id); 
    try (ResultSet rs = ps.executeQuery()) { 
     while (rs.next()) { 
     tmp = getDocumentDto(rs); 
     } 
     return tmp; 
    } 
    } catch (final SQLException ex) { 
    ex.printStackTrace(); 
    throw new DALException(ex.getMessage()); 
    } 
} 

@Override 
public DocumentDto addDocument(DocumentDto ddao) { 
    DocumentDto areturn = null; 
    mapPs.putIfAbsent("addDocument", bs.getPreparedStatement(addDocument)); 
    ps = mapPs.get("addDocument"); 

    try { 
    ps.setInt(1, ddao.getMobiliteDto().getId()); 
    ps.setBoolean(2, ddao.getContratBourse()); 
    ps.setBoolean(3, ddao.getConventionStage()); 
    ps.setBoolean(4, ddao.getCharteEtudiant()); 
    ps.setBoolean(5, ddao.getPreuveTestLinguistiqueBefore()); 
    ps.setBoolean(6, ddao.getDocumentEngagement()); 
    ps.setBoolean(7, ddao.getAttestationSejour()); 
    ps.setBoolean(8, ddao.getReleveNote()); 
    ps.setBoolean(9, ddao.getCertificatStage()); 
    ps.setBoolean(10, ddao.getRapportFinal()); 
    ps.setBoolean(11, ddao.getPreuveTestLinguistiqueAfter()); 
    try (ResultSet rs = ps.executeQuery()) { 
     if (rs.next()) { 
     areturn = getDocumentById(rs.getInt(1)); 
     } 
     return areturn; 
    } 
    } catch (SQLException ex) { 
    ex.printStackTrace(); 
    return null; 
    } 
} 

@Override 
public void updateDocument(DocumentDto ddto) { 
    mapPs.putIfAbsent("updateDocument", bs.getPreparedStatement(updateDocument)); 
    ps = mapPs.get("updateDocument"); 
    try { 
    ps.setInt(1, ddto.getMobiliteDto().getId()); 
    ps.setBoolean(2, ddto.getContratBourse()); 
    ps.setBoolean(3, ddto.getConventionStage()); 
    ps.setBoolean(4, ddto.getCharteEtudiant()); 
    ps.setBoolean(5, ddto.getPreuveTestLinguistiqueBefore()); 
    ps.setBoolean(6, ddto.getDocumentEngagement()); 
    ps.setBoolean(7, ddto.getAttestationSejour()); 
    ps.setBoolean(8, ddto.getReleveNote()); 
    ps.setBoolean(9, ddto.getCertificatStage()); 
    ps.setBoolean(10, ddto.getRapportFinal()); 
    ps.setBoolean(11, ddto.getPreuveTestLinguistiqueAfter()); 
    ps.setInt(12, ddto.getId()); 
    System.out.println(ps); 
    ps.executeUpdate(); 
    } catch (SQLException ex) { 
    throw new DALException(ex.getMessage()); 
    } 
} 
} 

Jede UCC Methode Open-Connection ruft dann Closeconnection.

Können Sie mir helfen, mein Problem zu beheben?

Antwort

0

Wenn Sie eine Verbindung schließen, wird sie an den Pool zurückgegeben, und alle daraus erstellten Anweisungen werden geschlossen (oder zumindest der Ihnen zugewiesene Proxy wird geschlossen). Dieses Verhalten wird von der JDBC-Spezifikation vorgeschrieben.

Wenn Sie Anweisungspooling haben möchten, sollten Sie die vom Verbindungspool bereitgestellten Funktionen verwenden und nicht versuchen, Ihre eigene Rolle zu übernehmen.

Für DBCP siehe BasicDataSource Configuration Parameters, speziell Einstellungen poolPreparedStatements und maxOpenPreparedStatements.