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

OptaPlanner排班应用无法添加租户问题求助

Fixing org.hibernate.PersistentObjectException When Adding a Tenant to OptaShift Employee Rostering

我之前在OptaShift Employee Rostering上也踩过这个坑,这个错误的核心原因很明确:Hibernate对实体状态的判定规则导致的。

你在POST请求里手动指定了id: 100,而后端的/rest/tenant/add接口应该是用JPA的persist()方法来处理新租户的。persist()只负责处理瞬时态实体——也就是还没有分配数据库主键的全新对象。当你给实体设置了id值,Hibernate会立刻把它标记为游离态实体(认为这个对象已经在数据库里存在过,只是当前不在Session管理范围内),这时候调用persist()就会触发这个异常。

下面是两种可行的解决办法:

方法1:让后端自动生成主键(推荐)

直接移除请求体里的id字段,把curl命令改成这样:

curl -X POST "http://localhost/rest/tenant/add" -H "accept: application/json" -H "content-type: application/json" -d "{ \"version\": 0, \"name\": \"Test\"}"

这里我把version改成了0——因为version是JPA乐观锁的字段,新创建的实体版本号默认从0开始,也可以直接去掉这个字段,后端会自动处理。这样实体就变成了瞬时态,persist()可以正常执行,后端会自动给这个新租户分配主键ID。

方法2:如果必须手动指定ID,改用合适的接口

如果业务场景要求你必须自定义租户ID,那你需要确认后端是否提供了支持游离态实体的接口(比如用merge()方法实现的save或update接口)。假设后端有/rest/tenant/save这样的接口,你可以把请求改成:

curl -X POST "http://localhost/rest/tenant/save" -H "accept: application/json" -H "content-type: application/json" -d "{ \"id\": 100, \"version\": 10, \"name\": \"Test\"}"

merge()方法的逻辑是:如果数据库里不存在ID为100的租户,就插入这条新数据;如果已经存在,就更新对应的记录,这样就不会触发游离态实体的异常了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:06:00