Spring-data-jpa:批量插入不起作用

Posted

技术标签:

【中文标题】Spring-data-jpa:批量插入不起作用【英文标题】:Spring-data-jpa: batch inserts are not working 【发布时间】:2021-03-09 09:13:38 【问题描述】:

我使用这个article 为我的一个实体使用 spring-data-jpa 实现批量插入。我正在使用 MS SQL DB。

我将主键生成策略从GenerationType.IDENTITY改为GenerationType.SEQUENCE

@Entity
@Table(name = "Answers")
public class AnswerDMO implements java.io.Serializable 
    private static final long serialVersionUID = 1L;
    private long id;
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "answer_new_generator")
    @SequenceGenerator(name = "answer_new_generator", sequenceName = "answer_new_sequence", allocationSize = 15)
    @Column(name = "Id", unique = true, nullable = false)
    public long getId() 
        return this.id;
    
    public void setId(long id) 
        this.id = id;
    

服务方法通过调用<S extends T> List<S> save(Iterable<S> entities);保存答案实体列表:

@Transactional
public List<AnswersDMO> saveAnswers () 
       /* other logic..... */
       if(!CollectionUtils.isEmpty(answersToSave)) 
            supplementalAnswerNewDAO.save(answersToSave);
        

为了告诉 Hibernate 在插入时使用批处理并检查它是否实际工作,我设置了以下 JPA 属性:

<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.hibernate.jdbc.batch_size">5</prop>
<prop key="hibernate.order_inserts">true</prop>

但是,在插入 11 个实体时,JDBC 批处理计数为 0:

(Log4j2-TF-1-AsyncLogger[AsyncContext@44f54c5e]-1)     0 nanoseconds spent releasing 0 JDBC connections;
(Log4j2-TF-1-AsyncLogger[AsyncContext@44f54c5e]-1)     65217828 nanoseconds spent preparing 6 JDBC statements;
(Log4j2-TF-1-AsyncLogger[AsyncContext@44f54c5e]-1)     727057697 nanoseconds spent executing 6 JDBC statements;
(Log4j2-TF-1-AsyncLogger[AsyncContext@44f54c5e]-1)     0 nanoseconds spent executing 0 JDBC batches;

休眠查询:

08:02:35,739 INFO  [stdout] (default task-1) Hibernate: 
08:02:35,740 INFO  [stdout] (default task-1)     select
08:02:35,742 INFO  [stdout] (default task-1)         next value for supplemental_answer_new_sequence

08:02:57,941 INFO  [stdout] (default task-1) Hibernate: 
08:02:57,941 INFO  [stdout] (default task-1)          insert 
08:02:57,941 INFO  [stdout] (default task-1)         into
08:02:57,941 INFO  [stdout] (default task-1)             my_schema.dbo.Answers
08:02:57,941 INFO  [stdout] (default task-1)             (CreatedDate, InstanceId, ProfileId, QuestionId, UpdatedDate, Value, Id) 
08:02:57,941 INFO  [stdout] (default task-1)         values
08:02:57,941 INFO  [stdout] (default task-1)             (?, ?, ?, ?, ?, ?, ?)

Q1:谁能告诉我为什么它不起作用?

Q2:另外,在我从 GenerationType.IDENTITY 切换到 GenerationType.SEQUENCE 后,我开始在日志中看到以下异常:

[jdbc.spi.SqlExceptionHelper] – SQL Error: 544, SQLState: S0001
[jdbc.spi.SqlExceptionHelper] – Cannot insert explicit value for identity column in table 'Answers' when IDENTITY_INSERT is set to OFF.

是因为id 列有identity 属性吗?如果是,解决的步骤是什么?

更新:我刚刚注意到我有一个错误的属性名称&lt;prop key="hibernate.hibernate.jdbc.batch_size"&gt;5&lt;/prop&gt;,它应该是&lt;prop key="hibernate.jdbc.batch_size"&gt;5&lt;/prop&gt;

所以主要问题现在是

[jdbc.spi.SqlExceptionHelper] – SQL Error: 544, SQLState: S0001
[jdbc.spi.SqlExceptionHelper] – Cannot insert explicit value for identity column in table 'Answers' when IDENTITY_INSERT is set to OFF.

有什么办法可以解决吗?

【问题讨论】:

【参考方案1】:

我面临着完全相同的问题。问题是在 JPA 创建的表中,ID 列被标记为 IDENTITY 列和 因此,JPA 生成的插入语句中这些 ID 列的显式值被 MSSql 服务器阻止。 另一个有趣的事实是,如果您通过 IntelliJ 数据库功能创建了“有问题的”表并且您已经注释了 ID 列作为主键和自动增量,然后它也被标记为 IDENTITY 列。所以解决方法如下:

    右键单击“有问题的”表 -> SQL 脚本 -> 生成 DDL 到查询控制台 放下桌子 从生成的查询中删除“身份”关键字 执行更改后的查询 重启数据库中的序列:ALTER SEQUENCE answer_new_sequence RESTART WITH 1; 我强烈建议 allocationSize 值与 hibernate.hibernate.jdbc.batch_size 值匹配,因为这将导致最小值 从序列中传递值。此外,allocationSize 必须与数据库中序列的步骤相匹配。 希望这会有所帮助。 干杯。

【讨论】:

以上是关于Spring-data-jpa:批量插入不起作用的主要内容,如果未能解决你的问题,请参考以下文章

从php执行时mssql批量插入不起作用

使用 Spring Boot 和 Spring Data JPA 批量插入不起作用

批量插入后选择在 MS access 数据库中不起作用

Spring -data-jpa ,存储库类不起作用

插入许多在 mongoDB 中不起作用,为啥?

使用文件名参数批量插入 [重复]