Maison >Java >javaDidacticiel >Réutilisation de PreparedStatement : réutiliser ou ne pas réutiliser ? Une plongée approfondie dans l'efficacité et l'évolutivité
Lorsqu'ils travaillent avec PreparedStatements dans une seule connexion sans pool de connexions, les développeurs sont souvent confrontés au dilemme de créer un nouveau instance pour chaque opération DML/SQL ou en réutilisant une instance existante. Ici, nous analysons les avantages et les inconvénients des deux approches et explorons une solution alternative pour améliorer l'efficacité et l'évolutivité.
La première approche consiste à recréer une nouvelle instance PreparedStatement pour chaque opération, garantir que chaque instruction est exempte de tout paramètre ou état résiduel des exécutions précédentes. Cependant, cette approche peut entraîner des pénalités de performances, en particulier dans les environnements multithread.
La deuxième approche résout ces problèmes en réutilisant une seule instance PreparedStatement, en effaçant ses paramètres avant chaque exécution. Bien que cette méthode soit un peu plus efficace, elle n'a pas l'élégance et la simplicité de la première approche.
Une solution plus optimale pour exécuter plusieurs opérations DML/SQL consiste à utiliser mise en lots. Cette technique consiste à collecter une série d'opérations et à les exécuter sous la forme d'une seule requête à la base de données. Le traitement par lots réduit considérablement la surcharge associée à la création et à la fermeture de plusieurs instances PreparedStatement.
<code class="java">public void executeBatch(List<Entity> entities) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { for (Entity entity : entities) { statement.setObject(1, entity.getSomeProperty()); // ... statement.addBatch(); } statement.executeBatch(); } }</code>
Dans les scénarios où le nombre de lots à exécuter est excessif, limiter la taille du lot peut améliorer encore les performances.
<code class="java">public void executeBatch(List<Entity> entities) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { int i = 0; for (Entity entity : entities) { statement.setObject(1, entity.getSomeProperty()); // ... statement.addBatch(); i++; if (i % 1000 == 0 || i == entities.size()) { statement.executeBatch(); // Execute every 1000 items. } } } }</code>
Les problèmes concernant la sécurité des threads sont atténués en utilisant l'instruction try-with-resources pour acquérir et fermer la connexion et PreparedStatement dans le même bloc de méthode :
<code class="java">try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { // ... }</code>
Dans les scénarios transactionnels, la désactivation de la validation automatique sur la connexion garantit la cohérence des données en validant la transaction uniquement une fois tous les lots terminés.
<code class="java">public void executeBatch(List<Entity> entities) throws SQLException { try (Connection connection = dataSource.getConnection()) { connection.setAutoCommit(false); try (PreparedStatement statement = connection.prepareStatement(SQL)) { // ... try { connection.commit(); } catch (SQLException e) { connection.rollback(); throw e; } } } }</code>
En tirant parti de l'exécution par lots et en adhérant aux techniques de gestion de connexion appropriées , les développeurs peuvent exploiter la puissance de PreparedStatements tout en maximisant l'efficacité et l'évolutivité, même dans des environnements multithread.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!