版本升级后异常
Exception after version upgrade
在使用 Optaplanner v7.11.0.Final 的项目上存在分数持久性问题,我升级到最新版本 (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.run(Application.java:222)
at org.optaplanner.plr.Application$$FastClassBySpringCGLIB$57a0d1.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$$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()
这样的方法很快就会失败,可能是在给 addProblemFactChange()
的回调中或在多线程求解中。无论如何,它无法根据该实体的 planningId 找到工作实体。
注意错误消息是如何说 planningId(通常是 Long
、String
、UUID
)是 class [=15 的一个实例=].这与您问题中的域模型相抵触,它说它是一个整数。请在抛出消息的地方设置一个断点并验证它。
潜在原因:
- 一般混合附加的 JPA 对象 - 我会怀疑
- 混合附加的 JPA 对象并在没有 JPA @Id 注释的方法上使用 OptaPlanner 的 @PlanningId 注释,导致 JPA 代理该方法。
无论哪种方式,在 OptaPlanner 中使用它们之前分离 JPA 对象都会修复它。请确认是否修复了它,因此我可以在错误消息中添加 "Maybe detach your JPA objects"。
感谢Geoffrey and yurloc的评论,我终于找到问题所在了。
首先,Etat
个对象通过与另一个对象的连接进入。将 ManyToOne
获取类型更改为 Eager
而不是 Lazy
表明我得到了相同的异常,但使用 Etat
对象而不是它们的 Hibernate 代理。
所以这意味着这些对象不被 Optaplanner 知道。事实上,我为 Etat
使用了每个计划变量的特定范围,但从未在问题事实中加载所有这些变量。
最后,它与分离对象和附加对象无关,并且可以将连接获取类型放回 Lazy
值。
在使用 Optaplanner v7.11.0.Final 的项目上存在分数持久性问题,我升级到最新版本 (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.run(Application.java:222)
at org.optaplanner.plr.Application$$FastClassBySpringCGLIB$57a0d1.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$$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()
这样的方法很快就会失败,可能是在给 addProblemFactChange()
的回调中或在多线程求解中。无论如何,它无法根据该实体的 planningId 找到工作实体。
注意错误消息是如何说 planningId(通常是 Long
、String
、UUID
)是 class [=15 的一个实例=].这与您问题中的域模型相抵触,它说它是一个整数。请在抛出消息的地方设置一个断点并验证它。
潜在原因: - 一般混合附加的 JPA 对象 - 我会怀疑 - 混合附加的 JPA 对象并在没有 JPA @Id 注释的方法上使用 OptaPlanner 的 @PlanningId 注释,导致 JPA 代理该方法。
无论哪种方式,在 OptaPlanner 中使用它们之前分离 JPA 对象都会修复它。请确认是否修复了它,因此我可以在错误消息中添加 "Maybe detach your JPA objects"。
感谢Geoffrey
首先,Etat
个对象通过与另一个对象的连接进入。将 ManyToOne
获取类型更改为 Eager
而不是 Lazy
表明我得到了相同的异常,但使用 Etat
对象而不是它们的 Hibernate 代理。
所以这意味着这些对象不被 Optaplanner 知道。事实上,我为 Etat
使用了每个计划变量的特定范围,但从未在问题事实中加载所有这些变量。
最后,它与分离对象和附加对象无关,并且可以将连接获取类型放回 Lazy
值。