0

최대 절전 모드를 사용하는 응용 프로그램에서 데이터베이스 매핑 문제를 해결하려고합니다. 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) 

감사

+0

게시 완료 stacktrace – Zulfi

+0

왜 MandtId에 @Embeddable 주석을 추가 했습니까? – Zulfi

+0

대부분의 예제 온라인 때문에이 작업을 수행했습니다. 그러나 당신은 옳습니다. 제 관점에서는 필요하지 않습니다. – Ben

답변

1

I에 유래 (https://stackoverflow.com/a/13147366/4563947)에 다른 곳에서 제안 된 해결 방법을 사용하여 문제를 스스로 해결할 수 있습니다.

MandtId.java

@SuppressWarnings("serial") 
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]"); 
} 

} 

EnumValue는 : 여기

작동 우리의 주석을 표시하는 코드의 일부 조각입니다.우리가 주석에도 중요는 등의 갱신과 비 갱신 제약을 혼합 논리적 이름을 찾을 수 없습니다와 자바

@Entity 
@IdClass(MandtId.class) 
public class EnumValue extends ReadWriteRecord { 

@Id 
@Column(name="Mandt") 
private String mandt; 

@Id 
@Column(name="EnumValueId") 
private String id; 

@ManyToOne(fetch=FetchType.EAGER, optional=false) 
    @JoinColumnsOrFormulas({ 
     @JoinColumnOrFormula(column= @JoinColumn(name="Mandt", referencedColumnName="Mandt", insertable=false, updatable=false)), 
     @JoinColumnOrFormula(column= @JoinColumn(name="EnumTypeId", referencedColumnName="EnumTypeId", insertable=false, updatable=false)) 
}) 
private EnumType enumType; 

...more but irrelevant code... 

EnumType.java는

@Entity 
@IdClass(MandtId.class) 
public class EnumType extends ReadWriteRecord { 

@Id 
@Column(name="Mandt") 
private String mandt; 

@Id 
@Column(name="EnumTypeId") 
private String id; 

@OneToMany(mappedBy="enumType", fetch=FetchType.EAGER) 
@OrderBy("sortIndex") 
private List<EnumValue> values; 

...more but irrelevant code... 

JoinColumnOrFormula 주석이 문제를 해결 ColumnOrFormula, 수식을 전혀 지정하지 않습니다. 수식을 사용하면 수식에서 열로 변환 할 때 문제가 발생했습니다.