You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同表插入多条记录时乐观锁触发NullPointerException问题解决

乐观锁实现中的NullPointerException问题分析与解决

问题背景

已完成乐观锁的基础配置:

  • 在数据库表txn_customer中创建了version字段
  • 实体类TxnCustomer中定义了带@Version注解的对应字段

实体类代码

@Entity
@Table(name = "txn_customer")
public class TxnCustomer implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "TXN_ID")
    private Integer txnId;

    @Version
    private Integer version;

    @Temporal(TemporalType.DATE)
    @Column(name = "TXN_DATE")
    private Date txnDate;

    @Column(name = "CASHMEMO_NUMBER")
    private Long cashmemoNumber;

    @Column(name = "INVOICE_AMOUNT")
    private double invoiceAmount;
    
}   

业务代码

@Transactional(propagation = Propagation.REQUIRED)
public TransactionResponseDTO saveTransaction(RequestDTO requestDTO) {
    TxnCustomer object1 = saveTxnCustomer(requestDTO);
    repo.save(object1);

    TxnCustomer object2 = saveTxnCustomer(requestDTO);
    repo.save(object2);
}   

核心异常信息

Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because "current" is null
    at org.hibernate.type.IntegerType.next(IntegerType.java:70) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
    at org.hibernate.type.IntegerType.next(IntegerType.java:22) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
    at org.hibernate.engine.internal.Versioning.increment(Versioning.java:92) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]

异常原因

这个空指针异常的核心原因是实体的version字段初始值为null。Hibernate在处理乐观锁逻辑时,会在事务提交前自动递增版本号,但当version为null时,Hibernate尝试调用intValue()方法将其转为基本类型int,就会触发NPE。

需要注意:即使数据库中version字段设置了默认值(如0),Hibernate也不会主动读取数据库默认值填充到内存中的实体对象,依然会使用null值进行版本递增操作。

解决方法

1. 直接在实体类中初始化version字段

给version字段设置默认初始值0,这是最直接有效的方式:

@Version
private Integer version = 0;

或者通过构造方法初始化:

public TxnCustomer() {
    this.version = 0;
}

2. 补充数据库字段配置并同步实体注解

如果希望依赖数据库默认值,需要同时完成两步:

  • 数据库表的version字段设置默认值0,且设置为非空
  • 实体类中添加对应注解,确保Hibernate感知字段约束:
@Version
@Column(name = "version", nullable = false, columnDefinition = "INT DEFAULT 0")
private Integer version;

不过这种方式仍需注意,部分Hibernate版本在插入新实体时,若内存中version为null,还是会优先使用null值,因此更推荐第一种实体初始化的方式。

3. 检查对象创建逻辑

确认saveTxnCustomer(requestDTO)方法在创建TxnCustomer对象时,是否正确初始化了version字段,若未设置则补充初始化逻辑。

内容的提问来源于stack exchange,提问作者Shiladittya Chakraborty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:17:16