Spring Data Jpa + MySQL IDENTITY 主键下批量插入最佳实践

Spring Data Jpa 虽然可以使用参数调整批量插入,但是仅限于主键策略不是 IDENTITY 的情况下,对于习惯了使用 IDENTITY 的 MySQL 选手来说,批量插入数据直接就悲剧了。

幸好我们还有 JdbcTemplate 这个利器,我们使用 Spring Data Jpa 的最佳实践就是使用接口继承 JpaRepository,接口里面是没法注入的,所以我们可以再定义一个 Batch 操作的接口

public interface AdminGroupPermissionBatchRepository {
    public void batchInsert(List<AdminGroupPermission> adminGroupPermissions);
}

然后我们的接口同时继承 Batch 这个接口,再单独写一个 Batch 接口的实现就好了,Spring Data Jpa 会全自动给我们搞定注入和调用的。Spring Boot 真香啊!

public class AdminGroupPermissionBatchRepositoryImpl implements AdminGroupPermissionBatchRepository {
    private final JdbcTemplate jdbcTemplate;

    public AdminGroupPermissionBatchRepositoryImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void batchInsert(List<AdminGroupPermission> adminGroupPermissions) {
        jdbcTemplate.batchUpdate("INSERT INTO " + AdminGroupPermission.TABLE_NAME + "(adminGroupId,actionId) values(?,?)",
                new BatchPreparedStatementSetter() {
                    @Override
                    public void setValues(PreparedStatement preparedStatement, int i)
                            throws SQLException {
                        AdminGroupPermission adminGroupPermission = adminGroupPermissions.get(i);

                        preparedStatement.setInt(1, adminGroupPermission.getAdminGroupId());
                        preparedStatement.setString(2, adminGroupPermission.getActionId());
                    }

                    @Override
                    public int getBatchSize() {
                        return adminGroupPermissions.size();
                    }
                });
    }
}

Resposity 接口类如下:

@Repository
public interface AdminGroupPermissionRepository extends JpaRepository<AdminGroupPermission, Integer>, AdminGroupPermissionBatchRepository {
    public List<AdminGroupPermission> findAllByAdminGroupId(Integer id);

    @Modifying
    @Transactional
    @Query("DELETE FROM AdminGroupPermission WHERE adminGroupId = ?1")
    public void deleteAllByAdminGroupId(Integer id);
}

以上只是主要代码片段