제공된 데이터베이스를 사용하여 값을 읽는 JavBeans + Hibernate 매핑으로 소스 라이브러리를 만들고 오픈 소스 라이브러리를 만들려고합니다 (읽기만하고 쓰기는하지 않음). 안타깝게도이 데이터베이스는 잘 설계되지 않았습니다.
내 문제는 선택적인 ManyToOne 관계에 있습니다. 즉, null이 될 수 있습니다.
다음은 두 테이블입니다 (첫 번째는 types
, 두 번째는 metaTypes
).
+--------+---------------+
| typeID | typeName |
+--------+---------------+
| 1 | Chair |
| 2 | Table |
| 3 | Picnic Table |
| 4 | Bedside Table |
+--------+---------------+
+--------+--------------+
| typeID | parentTypeID |
+--------+--------------+
| 3 | 2 |
| 4 | 2 |
+--------+--------------+
자, 이제이 모든 것이 어떻게 함께 속하는 지에 대한 문제가 있습니다. 유형 테이블에는 존재할 수있는 항목 목록과 같은 모든 유형의 유형이 있습니다.
두 번째 표에서는 이러한 것들이 함께 그룹화됩니다. 보시다시피, "picnic table"에는 metaTypes
테이블 유형 테이블의 하위 항목으로 테이블에 항목이 있습니다.
유형이 기본 유형 인 경우 metaTypes
테이블에 해당 항목이 없습니다 . 잘 설계된 데이터베이스에서는 최소한 NULL이있는 항목이 존재하는 것을 제외하고는 parentTypeID
되지만 그렇지 않습니다. 나는 이것을 콩 @NotFound(action = NotFoundAction.IGNORE)
에서 사용하여 해결했습니다 Type
.
실제 데이터베이스에는 metaType
추가 관련 정보를 포함 하는 테이블에 더 많은 열 이 있으므로 빈이 있어야합니다MetaType
.
이 긴 소개 후에 실제 질문이 발생합니다.
a Type
를 변형 ( MetaType
)에 매핑 하려면 어떻게해야 합니까?
이것은 내가 시도한 것입니다 (축약, 게터 및 세터 대부분 생략).
@Entity
@Table(name = "types")
public class Type {
@Id
private int typeID;
private String typeName, description;
// meta types/ variations
@OneToOne
@JoinColumn(name = "typeID", insertable = false, updatable = false, nullable = true)
@NotFound(action = NotFoundAction.IGNORE)
private MetaType metaType; // -> this works as expected
@OneToMany
@JoinColumn(name = "typeID", referencedColumnName = "parentTypeID")
@NotFound(action = NotFoundAction.IGNORE)
private List<MetaType> variations; // this doesn't work
/**
* This method is quite easy to explain: Either this type is a base
* type, in which case it has no metaType but holds the variations directly,
* or it is a dervied type, in which case we get it's parent type and list the
* variations of the parent type.
*/
public List<MetaType> getVariations () {
if (metaType != null) {
return metaType.getParentType().getVariations();
}
return variations;
}
}
@Entity
@Table (name = "metaTypes")
public class MetaType {
@Id
private int typeID;
private Integer parentTypeID;
// id <> object associations
@OneToOne (mappedBy = "metaType")
@JoinColumn(name = "typeID", insertable = false, updatable = false)
private Type type;
@OneToOne
@JoinColumn(name = "parentTypeID", referencedColumnName = "typeID", insertable = false, updatable = false)
private Type parentType;
}
목표는 분명해야합니다. "Bedside Table"을 쿼리한다고 가정 해 보겠습니다. metaType은 null이 아니지만 변형 목록은 있어야합니다.
"Table"유형을 쿼리했다고 가정 해 보겠습니다. 이 경우 MetaType이없고 @NotFound
주석 덕분에 자동으로 실패하고 metaType
필드에 null이 있습니다. 여태까지는 그런대로 잘됐다. 그러나 "Table"에는의 typeID
가 2
있으므로 variations
목록에 두 개의 항목이 포함될 것으로 예상 합니다. 그러나 대신 아래 예외가 발생합니다.
그러나 어떻게 든 이것이 작동하지 않으면 아래 예외가 발생합니다.
Exception in thread "main" java.lang.NullPointerException
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1456)
at org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:864)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:779)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:728)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1695)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
그렇다면 접근 방식에 무엇이 잘못되었으며 어떻게 작동하도록 할 수 있습니까?
좋아, 다음은 내가 한 방식이며 잘 작동하는 것 같습니다.
유형 엔티티
@Entity
public class Type {
@Id
@Column(name = "typeId")
private Integer id;
@Column(name="typeName")
private String name;
@OneToMany
@JoinColumn(name="parentTypeId")
List<MetaType> metaTypes;
}
my @OneToMany
는 mappedBy
속성을 사용하지 않습니다 . 이 경우 @JoinColumn
대신 사용 하고 있습니다. 이것은 단방향 관계입니다.
MetaType 엔티티
@Entity
public class MetaType {
@Id
private Integer id;
@MapsId
@OneToOne
@JoinColumn(name = "typeId")
private Type type;
@ManyToOne
@JoinColumn(name = "parentTypeId")
private Type parentType;
}
이제 주어진 예와 같이 주어진 유형을 복구하고 올바른 데이터를 얻습니다.
TypeService service = ...;
Type t = service.getTypeById(2);
System.out.println(t.getName());
for(MetaType mt : t.getMetaTypes()){
System.out.println("\t" + mt.getType().getName() + "-> " + mt.getParentType().getName());
}
이것은 출력을 생성합니다
Table
Picnic Table-> Table
Bedside Table-> Table
또한 변형이없는 유형에 대해서도 올바르게 작동합니다. 유형 2 (의자)를 쿼리하면 빈 변형 컬렉션이있는 의자가 표시됩니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다