批量插入现有数据:阻止JPA在每次插入之前进行选择 [英] Bulk inserting existing data: Preventing JPA to do a select before every insert

查看:390
本文介绍了批量插入现有数据:阻止JPA在每次插入之前进行选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用JPA(休眠)作为持久层的Spring Boot应用程序.

I'm working on a Spring Boot application that uses JPA (Hibernate) for the persistence layer.

我目前正在实现迁移功能.我们基本上将系统的所有现有实体转储到XML文件中.此导出还包括实体的ID.

I'm currently implementing a migration functionality. We basically dump all the existing entities of the system into an XML file. This export includes ids of the entities as well.

我遇到的问题位于另一侧,重新导入现有数据.在这一步中,XML再次转换为Java对象,并保存到数据库中.

The problem I'm having is located on the other side, reimporting the existing data. In this step the XML gets transformed to a Java object again and persisted to the database.

当尝试保存实体时,我使用的是EntityManager类的merge方法,该方法有效:一切都保存成功.

When trying to save the entity, I'm using the merge method of the EntityManager class, which works: everything is saved successfully.

但是,当我打开Hibernate的查询日志记录时,我看到在每个插入查询之前,都会执行一次选择查询,以查看具有该ID的实体是否已经存在.这是因为该实体已经具有我提供的ID.

However when I turn on the query logging of Hibernate I see that before every insert query, a select query is executed to see if an entity with that id already exists. This is because the entity already has an id that I provided.

我了解这种行为,实际上是有道理的.但是,我确定ID将不存在,因此对于我的情况而言,选择没有任何意义.我要保存成千上万的记录,这意味着要对大型表进行成千上万的选择查询,这将大大降低导入过程的速度.

I understand this behavior and it actually makes sense. I'm sure however that the ids will not exist so the select does not make sense for my case. I'm saving thousands of records so that means thousands of select queries on large tables which is slowing down the importing process drastically.

我的问题:有没有办法关闭在插入之前检查实体是否存在"?

My question: Is there a way to turn this "checking if an entity exists before inserting" off?

其他信息:

当我使用entityManager.persist()而不是合并时,出现此异常:

When I use entityManager.persist() instead of merge, I get this exception:

org.hibernate.PersistentObjectException:分离的实体传递给 坚持

org.hibernate.PersistentObjectException: detached entity passed to persist

为了能够使用提供的/提供的ID,我使用以下ID生成器:

To be able to use a supplied/provided id I use this id generator:

@Id
@GeneratedValue(generator = "use-id-or-generate")
@GenericGenerator(name = "use-id-or-generate", strategy = "be.stackoverflowexample.core.domain.UseIdOrGenerate")
@JsonIgnore
private String id;

生成器本身:

public class UseIdOrGenerate extends UUIDGenerator {

  private String entityName;

  @Override
  public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
      entityName = params.getProperty(ENTITY_NAME);
      super.configure(type, params, serviceRegistry);
  }

  @Override
  public Serializable generate(SessionImplementor session, Object object) 
  {
        Serializable id = session
            .getEntityPersister(entityName, object)
            .getIdentifier(object, session);

      if (id == null) {
        return super.generate(session, object);
      } else {
        return id;
      }
  }
}

推荐答案

如果您确定将永远不会更新数据库上的任何现有条目,并且应始终重新插入所有实体,那么我将使用persist操作而不是merge.

If you are certain that you will never be updating any existing entry on the database and all the entities should be always freshly inserted, then I would go for the persist operation instead of a merge.

每次更新

在这种情况下(将id字段设置为自动生成),唯一的方法是从id字段中删除生成注释,并将配置保留为:

In that case (id field being set-up as autogenerated) the only way would be to remove the generation annotations from the id field and leave the configuration as:

@Id
@JsonIgnore
private String id;

因此,基本上将ID设置为始终手动分配.然后,即使存在id,持久性提供程序也会将您的实体视为短暂的..这意味着persist将起作用,并且不会生成任何额外的选择.

So basically setting the id up for always being assigned manually. Then the persistence provider will consider your entity as transient even when the id is present.. meaning the persist would work and no extra selects would be generated.

这篇关于批量插入现有数据:阻止JPA在每次插入之前进行选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆