2016-05-01 4 views
0

Я пытаюсь реализовать один пул соединений, чтобы иметь многопоточное приложение (но без UOW).org.apache.commons.dbcp2.DelegatingPreparedStatement с адресом: «NULL» закрыт

У меня такая же проблема каждый раз, когда я пытаюсь вызвать любые методы после входа в систему.

Я получил эту ошибку: org.apache.commons.dbcp2.DelegatingPreparedStatement с адресом: «NULL» закрыт.

My prepareStatements хранится на Карте, чтобы использовать ее снова. Они никогда не закрываются. Класс

Мои услуги:

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(); 
    } 
    } 
} 

Существует Exemple из DAO для того, чтобы понять, как это работает:

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()); 
    } 
} 
} 

Каждый UCC методы вызывают OpenConnection затем CloseConnection.

Помогите мне решить проблему, пожалуйста?

ответ

0

Когда вы закрываете соединение, оно возвращается в пул и любые созданные из него заявления закрываются (или, по крайней мере, предоставленный вам прокси закрыт). Такое поведение обеспечивается спецификацией JDBC.

Если вы хотите иметь пул операторов, то вы должны использовать функциональные возможности, предоставляемые пулом соединений, а не пытаться выполнять роль самостоятельно.

Для DBCP см. BasicDataSource Configuration Parameters, в частности, настройки poolPreparedStatements и maxOpenPreparedStatements.