问题:
因项目JDK升级从11升到21,相应的Spring从2.x升级到3.x,Hiberante也从5.x升级到6.6. 然后在测试时发现如下代码报错
实体类User对应表users
java
@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(generator = "customerUUIDGenerator")
@GenericGenerator(
name = "customerUUIDGenerator",
strategy = "org.example.id.customerUUIDGenerator"
)
private UUID id;
@Version
private int version;
@Column(unique = true, nullable = false)
private String username;
}
自定义id生成器
java
public class CustomerUUIDGenerator implements IdentifierGenerator {
@Override
public Object generate(SharedSessionContractImplementor session, Object object) {
final EntityPersister entityPersister = session.getEntityPersister( null, object );
Object id = entityPersister.getIdentifier( object, session );
return null != id ? id : UUID.randomUUID();
}
}
代码中存在如下使用
java
...
public void addUser(UUID id, String name, String passwd) {
User user = new User();
user.setId(id);
user.setUsername(name);
userRepository.save(user);
}
上面代码报错: detached entity passed to persist 或者StaleObjectStateException
原因
Hibernate在保存时会先查数据库有没有该数据
如果无则判断实体是否新创建的,判断流程主要如下

- 先判断id是否为空
- 如果version为null且id为外键
- 依据unsavedStrategy判断,尽在返回false时报错,否则存入数据库
- id == null 则为true
- id为自定义id且该Generator的
allowAssignedIdentifiers
方法返回true,则返回null