web-dev-qa-db-fra.com

Comment définir autocommit sur false dans le modèle jdbc de printemps

Actuellement, je mets autocommit à false au printemps en ajoutant une propriété à un identifiant de bean source de données, comme ci-dessous:

   <property name="defaultAutoCommit" value="false" /> 

Mais j’ai besoin de l’ajouter spécifiquement à une seule méthode Java avant d’exécuter ma procédure ..__ J'ai utilisé le fragment de code ci-dessous.

  getJdbcTemplate().getDataSource().getConnection().setAutoCommit(false);

Mais la ligne ci-dessus ne définissait pas autocommit sur false? 
Est-ce que je manque quelque chose? 
ou n’importe quelle alternative pour définir autocommit dans une méthode Java spécifique avant le printemps

Merci

17
bad programmer

Le problème est que vous définissez autocommit sur une Connection, mais JdbcTemplate ne se souvient pas que Connection; au lieu de cela, il obtient une nouvelle Connection pour chaque opération et il peut s'agir ou non de la même instance Connection, en fonction de votre implémentation DataSource. Puisque defaultAutoCommit n'est pas une propriété sur DataSource, vous avez deux options:

  1. En supposant que votre source de données concrète ait un paramètre pour defaultAutoCommit (par exemple, org.Apache.commons.dbcp.BasicDataSource ), transformez la DataSource en votre implémentation concrète. Bien entendu, cela signifie que vous ne pouvez plus modifier votre DataSource dans votre configuration Spring, ce qui irait à l’encontre de l’injection de dépendance.

((BasicDataSource)getJdbcTemplate().getDataSource()).setDefaultAutoCommit(false);

  1. Définissez la variable DataSource sur une implémentation d'encapsuleur définissant AutoCommit sur false à chaque extraction d'une connexion.

    final DataSource ds = getJdbcTemplate().getDataSource();
    getJdbcTemplate().setDataSource(new DataSource(){
      // You'll need to implement all the methods, simply delegating to ds
    
      @Override
      public Connection getConnection() throws SQLException {
        Connection c = ds.getConnection();
        c.setAutoCommit(false);
        return c;
      }
    });
    
5
Yosef Weiner

Je viens de découvrir cela et je pensais que la solution aiderait quelqu'un même s'il est trop tard.

Comme l'a dit Yosef, la connexion obtenue en appelant la méthode getJdbcTemplate().getDataSource().getConnection() peut être ou non celle utilisée pour la communication avec la base de données pour votre opération.

Si vous souhaitez simplement tester votre script et non pas valider les données, vous pouvez utiliser une source de données Apache Commons DBCP avec la validation automatique définie. La définition du haricot est donnée ci-dessous:

/**
 * A datasource with auto commit set to false.
 */
@Bean
public DataSource dbcpDataSource() throws Exception {
    BasicDataSource ds = new BasicDataSource();
    ds.setUrl(url);
    ds.setUsername(username);
    ds.setPassword(password);
    ds.setDefaultAutoCommit(false);
    ds.setEnableAutoCommitOnReturn(false);
    return ds;
}

// Create either JdbcTemplate or NamedParameterJdbcTemplate as per your needs
@Bean
public NamedParameterJdbcTemplate dbcpNamedParameterJdbcTemplate() throws Exception {
    return new NamedParameterJdbcTemplate(dbcpDataSource());
}

Et utilisez cette source de données pour de telles opérations.

Si vous souhaitez valider vos transactions, je vous suggère d’avoir un bean supplémentaire de la source de données avec la validation automatique définie sur true, qui correspond au comportement par défaut.

J'espère que ça aide quelqu'un!

1
Nagendra Varma

Vous devrez faire pour chaque instruction exécutée par jdbcTemplate. Parce que pour chaque jdbcTemplate.execute () etc., il obtient une nouvelle connexion à partir du pool de connexions de la source de données. Vous devrez donc le définir pour la connexion que la connexion utilisée par jdbcTemplate pour cette requête. Donc, vous devrez faire quelque chose comme

 jdbcTemplate.execute("<your sql query", new PreparedStatementCallback<Integer>(){

        @Override
        public  Integer doInPreparedStatement(PreparedStatement stmt) throws SQLException, DataAccessException 
        {
            Connection cxn = stmt.getConnection();
            // set autocommit for that cxn object to false
            cxn.setAutoCommit(false);
            // set parameters etc in the stmt
            ....
            ....
            cxn.commit();
            // restore autocommit to true for that cxn object. because if the same object is obtained from the CxnPool later, autocommit will be false
            cxn.setAutoCommit(true);
            return 0;

        }
    });

J'espère que cela t'aides

1
Prabhu R

Vous devez obtenir la connexion actuelle. par exemple.

Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
    try {
        conn.setAutoCommit(false);

        /**
         * Your Code
         */
        conn.commit();
    } catch (SQLException e) {
        conn.rollback();
        e.printStackTrace();
    }
1
Sujan