[英]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.