问题描述
在使用Optaplanner v7.11.0.Final的项目上存在分数持久性问题,我升级到了最新版本(v7.25.0.Final),但出现以下异常:
Having problem with Score persistance on a project using Optaplanner v7.11.0.Final, I upgraded to the latest one (v7.25.0.Final) but got the following exception :
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时不会出现该异常.
I finally found that the exception does not appear when upgrading up to v7.17.0.Final.
自v7.18.0起完成了哪些工作,最终使代码失败了?
What have been done in since v7.18.0.Final that makes the code failing ?
如何解决?
有关更多信息,这是相对类
EDIT :For more information, here are the relative classes
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;
}
最后,这是有史以来最简单的配置:)
and finally, the simplest config ever :)
<?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)
推荐答案
感谢 Geoffrey answer 和 yurloc 注释,我终于找到了问题所在.
Thanks to Geoffrey answer and yurloc comments, I finally found what was the problem.
首先,Etat
个对象通过与另一个对象的联接而来.将ManyToOne
提取类型更改为Eager
而不是Lazy
表明,我遇到了相同的异常,但是使用了Etat
对象而不是其Hibernate代理.
First, Etat
objects were coming through a join with another object. Changing the ManyToOne
fetch type to Eager
instead of Lazy
showed that I got the same exception but with Etat
objects instead of their Hibernate proxies.
因此,这意味着Optaplanner无法识别这些对象.确实,我在Etat
的每个计划变量中使用了特定范围,但从未在问题事实中加载所有这些变量.
So it means that these objects were not know by Optaplanner. Indeed, I was using a specific range per planning variable for Etat
but never load all these ones in the problem facts.
最后,它与分离对象与附加对象无关,并且可以将联接获取类型放回Lazy
值.
In the end, it has nothing to do with detached vs attached objects and the join fetch type can be put back to Lazy
value.
这篇关于版本升级后例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!