PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Quel est le moyen le plus efficace de persister des milliers d'entités ?

Vous devez utiliser des insertions par lot.

  1. Créer une interface pour un référentiel personnalisé SomeRepositoryCustom
public interface SomeRepositoryCustom {

    void batchSave(List<Record> records);

}
  1. Créer une implémentation de SomeRepositoryCustom
@Repository
class SomesRepositoryCustomImpl implements SomeRepositoryCustom {

    private JdbcTemplate template;

    @Autowired
    public SomesRepositoryCustomImpl(JdbcTemplate template) {
        this.template = template;
    }

    @Override
    public void batchSave(List<Record> records) {
        final String sql = "INSERT INTO RECORDS(column_a, column_b) VALUES (?, ?)";

        template.execute(sql, (PreparedStatementCallback<Void>) ps -> {
            for (Record record : records) {
                ps.setString(1, record.getA());
                ps.setString(2, record.getB());
                ps.addBatch();
            }
            ps.executeBatch();
            return null;
        });
    }

}
  1. Étendez votre JpaRepository avec SomeRepositoryCustom
@Repository
public interface SomeRepository extends JpaRepository, SomeRepositoryCustom {

}

pour économiser

someRepository.batchSave(records);

Remarques

Gardez à l'esprit que même si vous utilisez des insertions par lots, le pilote de base de données ne les utilisera pas. Par exemple, pour MySQL, il faut ajouter un paramètre rewriteBatchedStatements=true à l'URL de la base de données. Il est donc préférable d'activer la journalisation SQL du pilote (et non Hibernate) pour tout vérifier. Peut également être utile pour déboguer le code du pilote.

Vous devrez décider de diviser les enregistrements par paquets dans la boucle

    for (Record record : records) { 

    }

Un chauffeur peut le faire pour vous, vous n'en aurez donc pas besoin. Mais mieux vaut déboguer cette chose aussi.

P. S. N'utilisez pas var partout.