[英]Exception after version upgrade
在使用 Optaplanner v7.11.0.Final 的项目上出现 Score 持久性问题,我升级到最新版本 (v7.25.0.Final) 但出现以下异常:
The externalObject (Etat(super=DbObject(id=11), libelle=RCD, ordre=60)) with planningId ((class plr.domain.Etat$HibernateProxy$EZnO4cSz,11)) has no known workingObject (null).
Maybe the workingObject was never added because the planning solution doesn't have a @ProblemFactCollectionProperty annotation on a member with instances of the externalObject's class (class plr.domain.Etat$HibernateProxy$EZnO4cSz).
终于发现升级到v7.17.0.Final时没有出现异常。
自 v7.18.0.Final 以来做了什么导致代码失败?
如何解决?
编辑:有关更多信息,这里是相关类
package org.optaplanner.plr.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import org.optaplanner.core.api.domain.lookup.PlanningId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Entity
public class Etat extends DbObject {
@Column
private String libelle;
@Column
private int ordre;
@Override
@PlanningId
public Integer getId() {
return super.getId();
}
}
和它的超类
package org.optaplanner.plr.domain;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import lombok.Data;
import lombok.EqualsAndHashCode;
@MappedSuperclass
@Data
@EqualsAndHashCode
public abstract class DbObject {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
}
最后,有史以来最简单的配置:)
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!-- To solve faster by saturating multiple CPU cores -->
<moveThreadCount>4</moveThreadCount>
<solutionClass>org.optaplanner.plr.domain.PlannifSolution</solutionClass>
<entityClass>org.optaplanner.plr.domain.Plannif</entityClass>
<scoreDirectorFactory>
<scoreDrl>org/optaplanner/plr/solver/score.drl</scoreDrl>
<initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
</scoreDirectorFactory>
<termination>
<secondsSpentLimit>1200</secondsSpentLimit>
<unimprovedSecondsSpentLimit>300</unimprovedSecondsSpentLimit>
</termination>
</solver>
整个轨迹是
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:782)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:763)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:318)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
at org.optaplanner.plr.Application.main(Application.java:64)
Caused by: java.lang.IllegalStateException: The move thread with moveThreadIndex (2) has thrown an exception. Relayed here in the parent thread.
at org.optaplanner.core.impl.heuristic.thread.OrderByMoveIndexBlockingQueue.take(OrderByMoveIndexBlockingQueue.java:142)
at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.forageResult(MultiThreadedLocalSearchDecider.java:187)
at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.decideNextStep(MultiThreadedLocalSearchDecider.java:157)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:70)
at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:88)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:191)
at org.optaplanner.plr.Application$1.run(Application.java:222)
at org.optaplanner.plr.Application$1$$FastClassBySpringCGLIB$$7557a0d1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at org.optaplanner.plr.Application$1$$EnhancerBySpringCGLIB$$c098b4dc.run(<generated>)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779)
... 5 common frames omitted
Caused by: java.lang.IllegalStateException: The externalObject (Etat(super=DbObject(id=11), libelle=RCD, ordre=60)) with planningId ((class org.optaplanner.plr.domain.Etat$HibernateProxy$YghGFDSA,11)) has no known workingObject (null).
Maybe the workingObject was never added because the planning solution doesn't have a @ProblemFactCollectionProperty annotation on a member with instances of the externalObject's class (class org.optaplanner.plr.domain.Etat$HibernateProxy$YghGFDSA).
at org.optaplanner.core.impl.domain.lookup.PlanningIdLookUpStrategy.lookUpWorkingObject(PlanningIdLookUpStrategy.java:66)
at org.optaplanner.core.impl.domain.lookup.LookUpManager.lookUpWorkingObject(LookUpManager.java:75)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.lookUpWorkingObject(AbstractScoreDirector.java:509)
at org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove.rebase(ChangeMove.java:85)
at org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove.rebase(ChangeMove.java:33)
at org.optaplanner.core.impl.heuristic.thread.MoveThreadRunner.run(MoveThreadRunner.java:139)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
我的理论:
您的代码已经有一个错误,但在 7.11 中,OptaPlanner 没有检测到它,也没有快速失败。 从 7.18 开始,它会检测和快速失败,以帮助您...
据我所知,没有ScoreDirector.lookUpWorkingObject()
,像ScoreDirector.lookUpWorkingObject()
这样的方法失败很快,可能是在给addProblemFactChange()
的回调中或在多线程解决中。 在任何情况下,它都无法根据该实体的 PlanningId 找到工作实体。
请注意错误消息如何说明 PlanningId (通常是Long
、 String
、 UUID
)是plr.domain.Etat$HibernateProxy$EZnO4cSz
类的一个实例。 这会影响您在问题中的域模型,它说它是一个整数。 在抛出消息的地方放置一个断点并验证这一点。
潜在原因: - 一般混入附加的 JPA 对象 - 我会怀疑 - 混入附加的 JPA 对象并在没有 JPA @Id 注释的方法上使用 OptaPlanner 的 @PlanningId 注释,导致 JPA 代理该方法。
无论哪种方式,在 OptaPlanner 中使用 JPA 对象之前分离它们都会修复它。 请确认是否修复了它,以便我可以在错误消息中添加“也许分离您的 JPA 对象”。
感谢Geoffrey 的回答和yurloc 的评论,我终于找到了问题所在。
首先, Etat
对象是通过与另一个对象连接而来的。 将ManyToOne
fetch 类型更改为Eager
而不是Lazy
表明我得到了相同的异常,但使用Etat
对象而不是它们的 Hibernate 代理。
所以这意味着 Optaplanner 不知道这些对象。 事实上,我为Etat
使用了每个计划变量的特定范围,但从未在问题事实中加载所有这些。
最后,它与分离对象和附加对象无关,连接获取类型可以放回Lazy
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.