同表插入多条记录时乐观锁触发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
相关产品推荐
相关产品推荐

