[SPRING] Hibernate를 통한 엔티티 저장시 org.hibernate.WrongClassException
SPRINGHibernate를 통한 엔티티 저장시 org.hibernate.WrongClassException
이 질문에서 나는 Hibernate 4.3.4.Final과 Spring ORM 4.1.2.RELEASE로 작업하고있다.
다음과 같이 Set of CardInstances를 보유하는 User 클래스가 있습니다.
@Entity
@Table
public class User implements UserDetails {
protected List<CardInstance> cards;
@ManyToMany
public List<CardInstance> getCards() {
return cards;
}
// setter and other members/methods omitted
}
@Table
@Entity
@Inheritance
@DiscriminatorColumn(name = "card_type", discriminatorType = DiscriminatorType.STRING)
public abstract class CardInstance<T extends Card> {
private T card;
@ManyToOne
public T getCard() {
return card;
}
}
@Table
@Entity
@Inheritance
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(name = "card_type", discriminatorType = DiscriminatorType.STRING)
public abstract class Card {
// nothing interesting here
}
몇 가지 유형의 카드가 있는데, 각각 카드 기본 클래스와 CardInstance 기본 클래스를 다음과 같이 확장합니다.
@Entity
@DiscriminatorValue("unit")
public class UnitCardInstance extends CardInstance<UnitCard> {
// all types of CardInstances extend only the CardInstance<T> class
}
@Entity
@DiscriminatorValue("leader")
public class LeaderCardInstance extends CardInstance<LeaderCard> {
}
@Entity
@DiscriminatorValue("unit")
public class UnitCard extends Card {
}
@Entity
@DiscriminatorValue("leader")
public class LeaderCard extends AbilityCard {
}
@Entity
@DiscriminatorValue("hero")
public class HeroCard extends UnitCard {
// card classes (you could call them the definitions of cards) can
// extend other types of cards, not only the base class
}
@Entity
@DiscriminatorValue("ability")
public class AbilityCard extends Card {
}
UnitCardInstance 또는 HeroCardInstance를 cards 컬렉션에 추가하고 엔티티를 저장하면 모든 것이 잘 동작합니다. 그러나 컬렉션에 AbilityCardInstance를 추가하고 엔티티를 저장하면 org.hibernate.WrongClassException으로 실패합니다. 게시물 끝에 정확한 예외 + 메시지를 추가했습니다.
몇 가지 질문을 읽었습니다. 기본 클래스의 컬렉션으로 작업하는 동안 게으른로드가 문제가되는 것 같습니다. 여기에 카드를 추가하고 저장하기 전에 User 엔터티를로드하는 방법은 다음과 같습니다.
User user = this.entityManager.createQuery("FROM User u " +
"WHERE u.id = ?1", User.class)
.setParameter(1, id)
.getSingleResult();
Hibernate.initialize(user.getCards());
return user;
"카드"에 대한 데이터베이스 항목 "cardinstances"에 대한 데이터베이스 항목
org.hibernate.WrongClassException: Object [id=1] was not of the specified subclass [org.gwentonline.model.cards.UnitCard] : Discriminator: leader
이 문제를 해결하는 방법에 대한 단서를 미리 알려 주셔서 감사합니다. 추가 정보가 필요하면 기꺼이 내 질문을 업데이트 할 것입니다!
해결법
-
==============================
1.@ManyToOne에 대한 JavaDocs의 첫 번째 단락에 따르면 :
@ManyToOne에 대한 JavaDocs의 첫 번째 단락에 따르면 :
그러나 귀하의 경우 @ManyToOne은 유형이 generic이고 generic 형식 정보가 컴파일 유형에서 지워집니다. 따라서, deserialize 할 때, Hibernate는 필드의 정확한 타입을 알지 못한다.
해결 방법은 targetEntity = Card.class를 @ManyToOne에 추가하는 것입니다. Card는 추상적이고 @Inheritance와 @DiscriminatorColumn 어노테이션을 가지고 있기 때문에, Hibernate는 모든 가능한 방법으로 실제 필드 타입을 해석해야한다. 이 작업은 Card 테이블의 판별 자 값을 사용하여 올바른 클래스 인스턴스를 생성합니다. 또한 Java 코드에서 유형 안전성을 유지합니다.
따라서 일반적으로 런타임에 필드 유형이 완전히 알려지지 않을 때마다 @ManyToOne 및 @OneToMany와 함께 targetEntity를 사용하십시오.
-
==============================
2.나는 그 문제를 해결했다.
나는 그 문제를 해결했다.
근본적인 원인은이 디자인에 있습니다.
@Table @Entity @Inheritance @DiscriminatorColumn(name = "card_type", discriminatorType = DiscriminatorType.STRING) public class CardInstance<T extends Card> { protected T card; } @Entity @DiscriminatorValue("leader") public class LeaderCardInstance extends CardInstance<LeaderCard> { }
런타임시 클래스의 제네릭 유형에 대한 정보는 Java에 없습니다. 자세한 내용은이 질문을 참조하십시오. Java generics - type erasure - 언제 어떻게됩니까?
즉, 최대 절전 모드에서는 CardInstance 클래스의 실제 유형을 판별 할 수 없습니다.
이것에 대한 해결책은 단순히 generic 형식을 제거하고 모든 클래스를 확장 (구현)하고 다음과 같은 하나의 클래스를 사용하는 것입니다.
@Table @Entity @Inheritance @DiscriminatorColumn(name = "card_type", discriminatorType = DiscriminatorType.STRING) public class CardInstance { Card card; }
회원 카드가 카드 유형에 대한 모든 정보를 가지고 있기 때문에 가능합니다 (그리고 더 좋은 디자인입니다).
나는 이것이 같은 문제에 부딪치게되면 사람들에게 도움이되기를 바랍니다.
from https://stackoverflow.com/questions/31257027/org-hibernate-wrongclassexception-on-saving-an-entity-via-hibernate by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 부트 액츄에이터 상태 표시기 (0) | 2019.05.20 |
---|---|
[SPRING] 스프링 MVC의 인터셉터 (0) | 2019.05.20 |
[SPRING] 이 Oracle 연결 오류가 발생하는 이유는 무엇입니까? ORA-12519, TNS : 적절한 서비스 처리기가 없습니다. (0) | 2019.05.20 |
[SPRING] @RequestMapping의 어떤 param이 호출되는지를 아는 법 (0) | 2019.05.20 |
[SPRING] org.springframework.beans.factory.CannotLoadBeanClassException : 이름이 ''인 bean에 대해 [com.Dao.ApplicationDaoImpl] 클래스를 찾을 수 없습니다. (0) | 2019.05.20 |