保存后如何获取非主键列的序列生成值(PostgreSQL+JPA)
问题描述
我在PostgreSQL数据库中创建了一个序列,用于插入时为orders表的非主键列order_number生成值,配置如下:
<createSequence sequenceName="order_number_seq" startValue="1" incrementBy="1" cacheSize="1"/> <addDefaultValue tableName="orders" columnName="order_number" defaultValueComputed="nextval('order_number_seq')"/>
保存订单后,order_number字段始终为null:
// 保存订单 order = orderRepository.save(order) // 这里 order.orderNumber 是 null sendEmail(order) // 这里需要用到 order_number indexOrder(order) // 这里也需要用到 order_number
实体类定义:
@Entity @Table(name = "orders") class Order( @Id val id: UUID = UUID.randomUUID(), @Column(name = "order_number", unique = true, nullable = false, updatable = false, insertable = false) var orderNumber: Long? = null, // 其他字段... )
我尝试在调用发送邮件和索引方法前,用orderRepository.findById(order.id)重新获取实体,但orderNumber仍然为null,该如何解决?
解决方案
1. 调整实体注解,让JPA主动同步序列值
你给orderNumber加了insertable=false,这会让JPA完全不把这个字段加入INSERT语句。虽然数据库会自动生成值,但JPA不知道要把这个值同步回实体对象。
修改实体类的字段注解,改用序列生成策略,同时保留updatable=false确保字段不可修改:
@Entity @Table(name = "orders") class Order( @Id val id: UUID = UUID.randomUUID(), @Column(name = "order_number", unique = true, nullable = false, updatable = false) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "order_number_seq") @SequenceGenerator(name = "order_number_seq", sequenceName = "order_number_seq", allocationSize = 1) var orderNumber: Long? = null, // 其他字段... )
这样JPA会在插入时主动调用序列生成值,并且直接把值同步回实体,保存后就能直接拿到orderNumber。
2. 强制刷新实体(不修改注解的临时方案)
如果暂时不想改实体注解,可以用EntityManager.refresh()强制从数据库拉取最新数据——findById无效是因为JPA一级缓存的存在,它会直接返回缓存里的旧对象,不会查数据库:
// 注入EntityManager @Autowired private lateinit var entityManager: EntityManager // 保存订单 order = orderRepository.save(order) // 强制刷新实体,同步数据库生成的order_number entityManager.refresh(order) sendEmail(order) indexOrder(order)
注意:这个操作需要在活跃事务中执行,否则会抛出异常。
3. 先确认数据库层面默认值是否生效
手动在数据库插入一条订单数据,检查order_number是否自动生成。如果数据库里都没值,说明你的DDL配置没正确执行,要检查序列是否存在、默认值是否绑定到order_number列。
内容的提问来源于stack exchange,提问作者user2342348
相关产品推荐
相关产品推荐

