최대 절전 모드를 사용하는 응용 프로그램에서 데이터베이스 매핑 문제를 해결하려고합니다. JPA를 사용하여 클래스에 주석을 달고 지금까지 성공했습니다. 그러나 이제 고객을 식별하는 고유 한 문자열과 함께 데이터베이스 항목을 식별하는 문자열과 함께 복합 키를 도입하려고합니다. 복합 키를 설정하려면 MandtId.java이라는 IdClass를 사용합니다.Hibernate JPA IdClass를 통해 복합 키를 사용하는 ManyToOne 외래 키 매핑이 열을 찾지 못함
그러나 다른 쪽에서 가입 할 열을 찾을 수 없어 매핑이 작동하지 않는 것처럼 보입니다. EnumValue.java
@Entity
@IdClass(MandtId.class)
public class EnumValue extends ReadWriteRecord {
@Id
@Column(name="mandt", insertable = false, updatable = false)
private String mandt;
@Id
@Column(name="enumValueId", insertable = false, updatable = false)
private String id;
@ManyToOne(fetch=FetchType.EAGER, optional=false)
@JoinColumns({
@JoinColumn(name="mandt", referencedColumnName="mandt", insertable = false, updatable = false),
@JoinColumn(name="enumTypeId", referencedColumnName="enumTypeId", insertable = false, updatable = false)
})
private EnumType enumType;
...more but irrelevant code...
EnumType.java
MandtId.java
@SuppressWarnings("serial")
@Embeddable
public class MandtId implements Serializable {
private String mandt;
private String id;
public MandtId() {
}
public MandtId(String mandt, String id) {
this.mandt = mandt;
this.id = id;
}
public String getId() {
return id;
}
public String getMandt() {
return mandt;
}
public void setId(String x) {
id = x;
}
public void setMandt(String x) {
mandt = x;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int hashCode = 0;
if (mandt != null) hashCode |= mandt.hashCode();
if (id != null) hashCode |= id.hashCode();
return hashCode;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object other) {
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof MandtId))return false;
MandtId otherMandtId = (MandtId)other;
return Objects.equals(mandt, otherMandtId.mandt) && Objects.equals(id, otherMandtId.id);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return (mandt != null ? mandt : "[null]") + "/" + (id != null ? id : "[null]");
}
}
: 여기
우리의 주석을 표시하는 코드의 일부 조각입니다@Entity
@IdClass(MandtId.class)
public class EnumType extends ReadWriteRecord {
@Id
@Column(name="mandt", insertable = false, updatable = false)
private String mandt;
@Id
@Column(name="enumTypeId", insertable = false, updatable = false)
private String id;
@OneToMany(mappedBy="enumType", fetch=FetchType.EAGER)
@OrderBy("sortIndex")
private List<EnumValue> values;
...more but irrelevant code...
ReadWriteRecord 클래스에는 id 관련 주석이없고 단지 추가 열만 있습니다.
ReadWriteRecord.java
@MappedSuperclass
public abstract class ReadWriteRecord extends PersistentRecord {
@Column
@Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime modifiedAt;
@Column
private String modifiedBy;
@Column
private boolean deleted;
public boolean getDeleted() {
return deleted;
}
public void setDeleted(boolean x) {
deleted = x;
}
public LocalDateTime getModifiedAt() {
return modifiedAt;
}
public String getModifiedBy() {
return modifiedBy;
}
public final void touch(UserContext context) {
final LocalDateTime timestamp = LocalDateTime.now(ZoneId.of("Z"));
onTouch(context, timestamp);
}
protected void onTouch(UserContext context, LocalDateTime timestamp) {
modifiedBy = context != null ? context.getUserId() : null;
modifiedAt = timestamp;
}
}
PersistendRecord.java
public abstract class PersistentRecord {
/**
* Indicates what to do when this record is passed to DatabaseSession.store().
* <ul>
* <li> if false, EntitiyManager.merge() is called.
* <li> if true, EntitiyManager.persist() is called.
* </ul>
* <p>This field is managed by the DatabaseSession and therefore not public.
* Users must call markNew() after the creation of new records.
*/
boolean mustInsert = false;
@Override
public String toString() {
return String.format("%s(%s - %s)", getClass().getSimpleName(), getMandt(), getId());
}
/**
* Returns the ID of the record, used by toString() and intended for generic logging.
* @return the primary key of the record, any format is allowed.
*/
public abstract String getId();
/**
* Returns the Mandant of the record, used by toString() and intended for generic logging.
* @return the primary key of the record, any format is allowed.
*/
public abstract String getMandt();
/**
* Sets the ID of the record.
* @param id primary key of the record.
*/
public abstract void setId(MandtId id);
/**
* Must be called after creating new entities so that EntitiyManager.persist() is called instead of EntitiyManager.merge().
*/
protected void markNew() {
mustInsert = true;
}
/**
* Can be called to force lazy loading.
*/
protected void fetch() { }
}
매핑과이 문제를 디버깅, 우리는 예외가 다음과 같은 메시지를 포함하는, 슬로우되는 것을 발견 할 때 :
논리적 이름을 가진 열을 찾을 수 없습니다 : org.hibernate.mapping.Table (EnumType) 및 관련 퍼 테이블과 보조 테이블 mandt 이후
열이 두 클래스에서가에 mandt를, 그것은 발견해야한다 . 이 문제를 해결하는 방법에 대한 제안 사항이 있으십니까? 나는 데이터베이스 스키마를 그대로 유지하는 것이 좋기 때문에 매핑 제안을 선호합니다.
스택 트레이스 :
javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceExcep tion(EntityManagerFactoryBuilderImpl.java:1249)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access$600(EntityManagerFactoryBuilderImpl.java:120)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:860)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at platform.data.DatabaseSession.<init>(DatabaseSession.java:94)
at platform.data.MandtDaoImpl.loadAllMandt(MandtDaoImpl.java:16)
at platform.data.Mandt.getMandt(Mandt.java:18)
at platform.data.Mandt.lambda$0(Mandt.java:10)
at platform.utils.Lazy.value(Lazy.java:24)
at platform.data.Mandt.deflt(Mandt.java:13)
at pm.business.InjectedLinkProject.getResourceTypes(InjectedLinkProject.java:66)
at pm.business.InjectedLinkProject.<init>(InjectedLinkProject.java:57)
at pm.business.PmLogic.<clinit>(PmLogic.java:17)
at main.business.MainApplication.<clinit>(MainApplication.java:22)
at main.application.MainController.<clinit>(MainController.java:25)
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$158$$anonfun$apply$158.apply(routes_routing.scala:2477)
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$158$$anonfun$apply$158.apply(routes_routing.scala:2477)
at play.core.Router$HandlerInvokerFactory$$anon$5.resultCall(Router.scala:267)
at play.core.Router$HandlerInvokerFactory$JavaActionInvokerFactory$$anon$15$$anon$1.invocation(Router.scala:255)
at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:55)
at play.core.j.JavaAction$$anonfun$11.apply(JavaAction.scala:82)
at play.core.j.JavaAction$$anonfun$11.apply(JavaAction.scala:82)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:40)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:46)
at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:32)
at scala.concurrent.impl.Future$.apply(Future.scala:31)
at scala.concurrent.Future$.apply(Future.scala:492)
at play.core.j.JavaAction$class.apply(JavaAction.scala:82)
at play.core.Router$HandlerInvokerFactory$JavaActionInvokerFactory$$anon$15$$anon$1.apply(Router.scala:252)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130)
at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:129)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:128)
at scala.Option.map(Option.scala:146)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:128)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:121)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:483)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:483)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:519)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:519)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:496)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:496)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: org.hibernate.MappingException: Unable to find column with logical name: mandt in org.hibernate.mapping.Table(EnumType) and its related supertables and secondary tables
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:582)
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:258)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:116)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1598)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1521)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1422)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
... 56 more
org.hibernate.MappingException: Unable to find column with logical name: mandt in org.hibernate.mapping.Table(EnumType) and its related supertables and secondary tables
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:582)
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:258)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:116)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1598)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1521)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1422)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at platform.data.DatabaseSession.<init>(DatabaseSession.java:94)
at platform.data.MandtDaoImpl.loadAllMandt(MandtDaoImpl.java:16)
at platform.data.Mandt.getMandt(Mandt.java:18)
at platform.data.Mandt.lambda$0(Mandt.java:10)
at platform.utils.Lazy.value(Lazy.java:24)
at platform.data.Mandt.deflt(Mandt.java:13)
at pm.business.InjectedLinkProject.getResourceTypes(InjectedLinkProject.java:66)
at pm.business.InjectedLinkProject.<init>(InjectedLinkProject.java:57)
at pm.business.PmLogic.<clinit>(PmLogic.java:17)
at main.business.MainApplication.<clinit>(MainApplication.java:22)
at main.application.MainController.<clinit>(MainController.java:25)
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$158$$anonfun$apply$158.apply(routes_routing.scala:2477)
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$158$$anonfun$apply$158.apply(routes_routing.scala:2477)
at play.core.Router$HandlerInvokerFactory$$anon$5.resultCall(Router.scala:267)
at play.core.Router$HandlerInvokerFactory$JavaActionInvokerFactory$$anon$15$$anon$1.invocation(Router.scala:255)
at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:55)
at play.core.j.JavaAction$$anonfun$11.apply(JavaAction.scala:82)
at play.core.j.JavaAction$$anonfun$11.apply(JavaAction.scala:82)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:40)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:46)
at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:32)
at scala.concurrent.impl.Future$.apply(Future.scala:31)
at scala.concurrent.Future$.apply(Future.scala:492)
at play.core.j.JavaAction$class.apply(JavaAction.scala:82)
at play.core.Router$HandlerInvokerFactory$JavaActionInvokerFactory$$anon$15$$anon$1.apply(Router.scala:252)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130)
at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:129)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:128)
at scala.Option.map(Option.scala:146)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:128)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:121)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:483)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:483)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:519)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:519)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:496)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:496)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
감사
게시 완료 stacktrace – Zulfi
왜 MandtId에 @Embeddable 주석을 추가 했습니까? – Zulfi
대부분의 예제 온라인 때문에이 작업을 수행했습니다. 그러나 당신은 옳습니다. 제 관점에서는 필요하지 않습니다. – Ben