如何在@JoinColumn字段插入null?Position实体parentUser设空插入报错
数据库表结构
CREATE TABLE IF NOT EXISTS users ( id BIGSERIAL PRIMARY KEY ); CREATE TABLE IF NOT EXISTS positions ( id BIGSERIAL PRIMARY KEY, parent_user_id BIGINT, -- 允许为null,因此未设置REFERENCES users (id) user_id BIGINT REFERENCES users (id) );
对应的Java实体类
@Table(name = "users") @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ToString.Exclude @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) private Set<Position> positions; } @Table(name = "positions") @Entity public class Position { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ToString.Exclude @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @ToString.Exclude @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parent_user_id", columnDefinition = "BIGINT") private User parentUser; }
插入时出现的错误
2022-11-21 18:24:21:934 ERROR i.n.c.impl.ErrorListenerLoggerImpl -
exceptionOccurred, Connection: 207475, Exception:
org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.TransientPropertyValueException: object references an
unsaved transient instance - save the transient instance before
flushing : ltd.package.model.Position.parentUser ->
ltd.package.model.User; nested exception is
java.lang.IllegalStateException:
org.hibernate.TransientPropertyValueException: object references an
unsaved transient instance - save the transient instance before
flushing : ltd.package.model.Position.parentUser ->
ltd.package.model.User
回答
完全可以插入parentUser为null的Position,报错的根源不是parentUser为null,而是你传入的parentUser是一个未持久化的瞬态User对象,而非真正的null值。
原因分析
Hibernate抛出的TransientPropertyValueException明确提示:对象引用了未保存的瞬态实例,需要先保存该实例再执行刷新操作。这说明你在创建Position时,给parentUser赋值了一个new User()但还没保存到数据库的对象,而不是将parentUser设为null。
解决办法
- 若要实现parentUser为null的业务逻辑,直接不给parentUser赋值,或者显式设置
position.setParentUser(null),确保不会传入未持久化的User实例。 - 如果确实需要关联新用户,需先将该User保存到数据库(获取持久化后的对象),再关联到Position;或者在
@ManyToOne注解上添加cascade = CascadeType.PERSIST级联保存配置,但这不符合你当前要parentUser为null的需求。
内容的提问来源于stack exchange,提问作者Pavel

