如何在 JPA 和自定义 UUID 标识符中实现批量插入

Posted

技术标签:

【中文标题】如何在 JPA 和自定义 UUID 标识符中实现批量插入【英文标题】:How to implement Batch insert in JPA and a Custom UUID Identifier 【发布时间】:2021-08-02 17:04:13 【问题描述】:

所以,我使用 Springboot 和 Data-JPA 和 POSTGRESQL 将数据插入表中:

@Entity
@Builder
@Data
class Person
    @Id
    UUID id;
    String name;

以及它的存储库

@Repository
interface PersonRepository extends JPARepository<Person, UUID>

假设我们创建了一个人员列表。

List<Person> persons = List.of(....)
Lets assume we have 10 persons in the list..

现在,当我执行 personRepository.saveAll(persons);

所以我遇到了这些问题:

    insert 之前有 10 个 insert 语句和 select select 语句。 我想要大小为 5 的批量插入,因此我想要在此处触发 2 个多值插入语句,但正在触发 10 个插入。

现在,我在自定义存储库的帮助下解决了第 1 点

public interface CustomBaseRepository<T, ID extends Serializable> 

    <S extends T> S customInsert(S entity);

    <S extends T> Collection<S> customInsertAll(Collection<S> entities);

    <S extends T> Collection<S> customSaveAllInBatch(Collection<S> entities);

@Transactional
public class CustomBaseRepositoryImpl<T, ID extends Serializable> implements CustomBaseRepository<T, ID> 

    @Autowired
    private final EntityManager entityManager;

    public CustomBaseRepositoryImpl(EntityManager entityManager) 
        this.entityManager = entityManager;
    


    @Override
    public <S extends T> S customInsert(S entity) 
        entityManager.persist(entity);
        return entity;
    

    @Override
    public <S extends T> Collection<S> customInsertAll(Collection<S> entities) 
        entities.forEach(entityManager::persist);
        return entities;
    

    @Override
    <S extends T> Collection<S> customSaveAllInBatch(Collection<S> entities)
       **//TODO(...): HOW TO DO THIS?**
    


所以我创建了我的自定义存储库并公开了 EntityManager 并进行了持久化,因为我知道当我保存“人员”列表时,它都是新记录。

现在,SELECT before INSERT 问题已修复,但批量插入问题仍然存在..

我也尝试使用 personRepository.saveAll(persons),但没有用,我在应用程序属性中使用这些命令也启用了批处理,但无法使其工作。

请帮助我实现批量插入,即在单个插入语句中插入多条记录..

我尝试使用这些属性但没有用:

spring.jpa.properties.hibernate.jdbc.batch_size
spring.jpa.properties.hibernate.jdbc.order_inserts
Also for URL:
reWriteBatchedInserts was enabled. 

请帮帮我..

【问题讨论】:

【参考方案1】:
    只需修改您的实体以在插入之前自动生成实体 ID。并且选择会消失。无需为此创建自定义存储库
@Entity
@Builder
@Data
class Person
    @Id
    @GeneratedValue(generator = "uuid") // new line !!!
    @GenericGenerator(name = "uuid", strategy = "uuid2") //new line !!
    UUID id;
    String name;

    至于批量插入,您使用我之前的建议并使用 vanilla Spring Data 存储库后,您可能想试试这个
spring.jpa.properties.hibernate.jdbc.batch_size=10
spring.jpa.properties.hibernate.order_inserts=true

【讨论】:

1.但是,由于我需要 Java 层中预先存在的人员 ID 进行其他计算,所以我继续采用这种方法,是否有任何其他优化方法来处理您在 Java 层上生成 ID 并仅实现的情况插入没有选择? 2. 我尝试使用第二部分 w.r.t 到 1 中提到的步骤,我仍然得到多个插入。 嗯。让我想想。另外,您确定将人员保存到数据库后不能进行其他计算吗? 嗯,是的,我需要在持久化之前预先计算 ID。 请告诉我,你怎么知道批次实际上并没有发生? 我启用了休眠日志,所以我给出了 2 的批量大小,并且节省了 10 人,所以最终应该触发 5. 查询,对吗?但我看到了 10 个插页。我希望我做对了

以上是关于如何在 JPA 和自定义 UUID 标识符中实现批量插入的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 UUID 字段而不是 JPA 的主键?

JPA 2.0 + 一对一 + 未设置共享主键

JAX-RS 和自定义授权

JPA注解主键生成策略-UUID

NSManagedObjectID 与自定义 UUID 标识符属性 - 获取性能

如何在jpa中实现自动增量