关于通过Hibernate保存实体的org.hibernate.WrongClassException [英] org.hibernate.WrongClassException on saving an entity via Hibernate

查看:1053
本文介绍了关于通过Hibernate保存实体的org.hibernate.WrongClassException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个User类,它拥有一个Set CardInstances是这样的:

  @Entity 
@Table
public class User实现UserDetails {

保护列表< CardInstance>牌;

@ManyToMany
public List< CardInstance> getCards(){
返回卡;
}

// setter和其他成员/方法省略
}

@Table
@Entity
@Inheritance
@DiscriminatorColumn(name =card_type,discriminatorType = DiscriminatorType.STRING)
public abstract class CardInstance< T extends Card> {

私人T卡;

@ManyToOne
public T getCard(){
return card;


$ b @Table
@Entity
@Inheritance
@ DiscriminatorOptions(force = true)
@DiscriminatorColumn( name =card_type,discriminatorType = DiscriminatorType.STRING)
public abstract class Card {
//这里没有什么有趣的东西
}

我有几种类型的卡片,分别扩展卡片基类和CardInstance基类,如下所示:

  @Entity 
@ DiscriminatorValue(unit)
公共类UnitCardInstance扩展CardInstance< UnitCard> {
//所有类型的CardInstances只扩展CardInstance< T> class
}

@Entity
@ DiscriminatorValue(leader)
public class LeaderCardInstance扩展CardInstance< LeaderCard> {

}






<$ p $ b $ @Entity
@DiscriminatorValue(unit)
公共类UnitCard扩展卡{
}

@Entity
@ DiscriminatorValue(leader)
public class LeaderCard扩展AbilityCard {
}

@Entity
@ DiscriminatorValue(hero)
public class HeroCard扩展UnitCard {
//卡类(你可以称它们为卡的定义)
//可以扩展其他类型的卡,不仅是基类
}

@Entity
@ DiscriminatorValue(ability)
公共类AbilityCard扩展卡{
}

如果我将一个UnitCardInstance或一个HeroCardInstance添加到cards集合中,并保存该实体,则一切正常。
但是,如果我将一个AbilityCardInstance添加到集合中并使用org.hibernate.WrongClassException保存实体,它将失败。我在帖子的底部添加了确切的异常+消息。



我读过一些问题,在处理基本集合时,延迟加载似乎是一个问题类,所以这里是我加载用户实体,然后添加卡并保存它:

  User user = this.entityManager。 createQuery(FROM User u+ 
WHERE u.id =?1,User.class)
.setParameter(1,id)
.getSingleResult();

Hibernate.initialize(user.getCards());

返回用户;






cards的数据库条目



的数据库条目 cardinstances







  org.hibernate.WrongClassException:Object [id = 1]不是指定的子类[org.gwentonline .model.cards.UnitCard]:Discriminator:leader 

预先感谢任何线索如何解决这个问题问题。如果您需要更多的信息,我会很乐意更新我的问题! 根据 @ManyToOne 的JavaDocs第一段:


通常不需要明确指定目标实体,因为它通常可以从类型中推断出来

然而,在你的情况下, @ManyToOne 在类型为泛型的字段上,并且泛型类型信息在编译类型中被擦除。因此,在反序列化时,Hibernate并不知道字段的确切类型。



解决方法是添加 targetEntity = Card.class @ManyToOne 。由于摘要,并且 @Inheritance 和 @DiscriminatorColumn 注解,这迫使Hibernate通过所有可能的方式来解析实际的字段类型。它使用 Card 表的鉴别器值来执行此操作并生成正确的类实例。另外,您在Java代码中保留了类型安全。






所以,一般来说,只要有字段类型在运行时不完全知道,请使用 targetEntity @ManyToOne @OneToMany


In this question I am working with Hibernate 4.3.4.Final and Spring ORM 4.1.2.RELEASE.

I have an User class, that holds a Set of CardInstances like this:

@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
}

I have several types of cards, each extending the Card base class and the CardInstance base class respectivly like this:

@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 {
}

If I add a UnitCardInstance or a HeroCardInstance to the cards collection and save the entity everything works fine. But if I add a AbilityCardInstance to the collection and save the entity it fails with a org.hibernate.WrongClassException. I added the exact exception + message at the bottom of the post.

I read through some questions, and lazy loading seems to be a problem while working with collections of a base class, so here is how I load the User entity before adding the card and saving it:

User user = this.entityManager.createQuery("FROM User u " +
                "WHERE u.id = ?1", User.class)
                .setParameter(1, id)
                .getSingleResult();

        Hibernate.initialize(user.getCards());

        return user;


The database entries for "cards"

The database entries for "cardinstances"


org.hibernate.WrongClassException: Object [id=1] was not of the specified subclass [org.gwentonline.model.cards.UnitCard] : Discriminator: leader

Thanks in advance for any clues how to fix this problem. If you need additional information I will gladly update my question!

解决方案

According to the first paragraph of the JavaDocs for @ManyToOne:

It is not normally necessary to specify the target entity explicitly since it can usually be inferred from the type of the object being referenced.

However, in your case, @ManyToOne is on a field whose type is generic and generic type information gets erased at the type of compilation. Therefore, when deserializing, Hibernate does not know the exact type of the field.

The fix is to add targetEntity=Card.class to @ManyToOne. Since Card is abstract and has @Inheritance and @DiscriminatorColumn annotations, this forces Hibernate to resolve the actual field type by all possible means. It uses the discriminator value of the Card table to do this and generates the correct class instance. Plus, you retain type safety in your Java code.


So, in general, whenever there is the chance of a field's type not being known fully at runtime, use targetEntity with @ManyToOne and @OneToMany.

这篇关于关于通过Hibernate保存实体的org.hibernate.WrongClassException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆