我用了这个article为我的一个实体使用 spring-data-jpa 实现批量插入。我正在使用 MS SQL 数据库。
我从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>
(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;
hibernate 查询:
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
属性(property)?如果是,解决的步骤是什么?
更新:我刚刚注意到我的属性名称有误 <prop key="hibernate.hibernate.jdbc.batch_size">5</prop>
,应该是<prop key="hibernate.jdbc.batch_size">5</prop>
.
所以现在的主要问题是
[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.
有什么办法可以解决吗?
最佳答案
我遇到了完全相同的问题。问题是在 JPA 创建的表中,ID 列被标记为 IDENTITY 列和 结果,由 JPA 生成的插入语句中这些 ID 列的显式值被 MSSql 服务器阻止。 另一个有趣的事实是,如果您通过 IntelliJ 数据库功能创建了“有问题的”表并且您已经注释了 ID 列作为主键和自动递增,然后它也被标记为 IDENTITY 列。所以解决方案如下:
- 右键单击“有问题的”表 -> SQL 脚本 -> 生成 DDL 以查询控制台
- 放下 table
- 从生成的查询中删除“identity”关键字
- 执行修改后的查询
- 重新启动数据库中的序列:ALTER SEQUENCE answer_new_sequence RESTART WITH 1;
- 我强烈建议 allocationSize 值与 hibernate.hibernate.jdbc.batch_size 值匹配,因为这将导致最小值 从序列中传递值。此外,allocationSize 必须与数据库中序列的步骤相匹配。 希望这会有所帮助。 干杯。
关于java - Spring-data-jpa:批量插入不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65022904/