0

我正在尝试制作一个可以在数据库中保存大量结构化对象的应用程序。现在我正在使用 Spring Data JPA(使用 hibernate + MySQL(MyIsam 表 + 外键))使用 Spring Data 存储库为数据服务编写代码既简单又愉快,但性能太慢了。

例如,我尝试在一张表中插入 100 条记录,需要 8.5 秒。

我尝试直接在 MySQL cmd 中执行相同的插入操作(在过程中使用硬编码的“插入字符串”),它显示了时间 - 0.85 秒。即使这样的结果对我来说也太慢了,但这是 MySQL 的问题

阅读论坛我发现帖子说 Spring Data JPA 不能正确地进行批量插入。

如何让我的应用程序更快?我想使用大小为 1000 或更大的批量 INSERT 操作。

由于我无法将我的对象一次性存储到数据库中(尽管批量大小),情况变得复杂

为了更清楚:

The objectGame contains list of objectRound
The objectGame also contains list of objectGamePlayer
The objectRound contains list of objectRoundCard
The objectGamePlayer contains list of objectPlayerCard
The objectGamePlayer also contains list of objectPlayerBet

当然,要插入一个 objectGame,它需要执行几个步骤: 插入大量 objectGame 并获取它们的 Id 拥有 objectGame 的 Id 插入大量 objectRound 并获取它们的 Id ...等等

哪种方式更适合我?

使用 Spring Data JPA、jdbc、hibernate、myBatis?还是另一种方式?

4

1 回答 1

0

您是对的,默认情况下 Spring Data JPA 不会以有效的方式进行批量插入。当我们想将超过 25000 个对象批量写入一个表并且我们有 8 个这样的表要写入时,我们遇到了这个问题。这是我们如何做到的。

默认情况下,Spring Data JPA 会将对象获取到 EntityManager 的缓存中,然后比较并决定是调用持久化还是合并。我绕过了这个逻辑,因为我根据版本知道我是要坚持还是合并。诀窍是根据if (entity.getVersion() == 0) {

public List<T> update(Collection<T> entities) {
        List<T> ret =  new ArrayList<>();
        EntityManager em = getEntityManager();
        for (T entity : entities) {
            if (entity.getVersion() == 0) {
                em.persist(entity);
                ret.add(entity);
            } else {
                ret.add(em.merge(entity));
            }
        }
        return ret;
    }

您将需要 EntityManager 的句柄,您可以通过创建自己的 JPA 存储库实现来获得它,只需扩展 SimpleJpaRepository 类。

import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;

public class MyJpaRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {

    private EntityManager entityManager;

    public MyJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        
        // Keep the EntityManager around to used from the newly introduced methods.
        this.entityManager = entityManager;
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }
}

并在应用程序的 SpringConfig 上添加以下注释来实例化您的 repo 实现,而不是使用默认的 SimpleJpaRepository@EnableJpaRepositories(basePackages = "..." , repositoryBaseClass = MyJpaRepositoryImpl.class)

@Configuration
@EnableJpaRepositories(basePackages = "au.com.xyz.infrastructure.repositories" , repositoryBaseClass = MyJpaRepositoryImpl.class)
@ComponentScan(basePackages = {"au.com.xyz.infrastructure.repositories.plugin", "au.com.xyz.infrastructure.repositories.external", ...})

public class InfrastructureSpringConfig {
于 2021-06-03T13:11:52.567 回答