Hibernate:具有单个多态表和相同联接列的双向递归一对多关系

时间:2019-07-09 06:44:54

标签: java hibernate

我正在开发一个应用程序,该应用程序处理几种不同类型的产品,即旅游(如观光旅游或类似旅游),这些旅游的变体和选项(可以与旅游一起预订的可选附加组件)

上述所有产品类型,思想名称,描述,持续时间等都存在无数的属性,因此建模这些属性的最合适方法是使用(抽象)Product类和单个产品表以及TourTourVariantOption的三个单独的子类,每个子类都直接扩展Product。游览变体和选项都完全属于一个父游览,因此,每个游览可以具有任意数量的变体和选项。

省略非必需位,这是我们当前的设置:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="subclazz", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value="-") // this "root" class is essentially abstract
public class Product implements Comparable<Product> {

    private Long id;
    //more properties that are used for any type of product

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    //getters & setters, hashcode, equals and compareTo methods

}

@Entity
@DiscriminatorValue(value="TOUR")
public class Tour extends Product {

    private SortedSet<Option> options = new TreeSet<Option>();
    private SortedSet<TourVariant> variants = new TreeSet<TourVariant>();
    //some tour specific properties


    @OneToMany(mappedBy="tour",fetch=FetchType.LAZY)
    @SortNatural
    @OnDelete(action=OnDeleteAction.CASCADE)
    @Cascade({CascadeType.PERSIST, CascadeType.MERGE, CascadeType.SAVE_UPDATE})
    public SortedSet<Option> getOptions() {
        return this.options;
    }
    public void setOptions(SortedSet<Option> options) {
        this.options = options;
    }
    public boolean addOption(Option option) {
        option.setTour(this);
        return this.options.add(option);
    }
    public boolean removeOption(Option option) {
        option.setTour(null);
        return this.options.remove(option);
    }

    @OneToMany(mappedBy="tour",fetch=FetchType.LAZY)
    @SortNatural
    @OnDelete(action=OnDeleteAction.CASCADE)
    @Cascade({CascadeType.PERSIST, CascadeType.MERGE, CascadeType.SAVE_UPDATE})
    public SortedSet<TourVariant> getVariants() {
        return this.variants;
    }
    public void setVariants(SortedSet<TourVariant> variants) {
        this.variants = variants;
    }
    public boolean addVariant(TourVariant variant) {
        variant.setTour(this);
        return this.variants.add(variant);
    }
    public boolean removeVariant(TourVariant variant) {
        variant.setTour(null);
        return this.variants.remove(variant);
    }

}

@Entity
@DiscriminatorValue(value="VARIANT")
public class TourVariant extends Product {

    private Tour tour;
    //some tour variant specific properties

    @ManyToOne
    @JoinColumn(name = "variant_tour_id") // <- Any way to make this work with the same join column, e.g. tour_id?
    public Tour getTour() {
        return this.tour;
    }
    public void setTour(Tour tour) {
        this.tour = tour;
    }

}


@Entity
@DiscriminatorValue(value="OPTION")
public class Option extends Product {

    private Tour tour;
    //some option specific properties

    @ManyToOne
    @JoinColumn(name = "option_tour_id") // <- Any way to make this work with the same join column, e.g. tour_id?
    public Tour getTour() {
        return this.tour;
    }
    public void setTour(Tour tour) {
        this.tour = tour;
    }

}

如上所示,我们必须使用不同的variant_tour_idoption_tour_id列,到目前为止,我们还找不到能够允许我们使用相同联接列的解决方案,例如tour_id将Option类和TourVariant类都加入其父级Tour。

可悲的是,当我们尝试访问关系tour.getVariants()tour.getOptions()时,总是会导致Hibernate吐出假人。

org.hibernate.WrongClassException: Object [id=2] was not of the specified subclass [xyz.model.TestOption] : loaded object was of wrong class class xyz.model.TestVariant

鉴于需要这种关系回到其父级Tour的产品只能是TourVariant或Option,并且辨别器subclazz可以清楚地识别每个产品,有什么方法可以做到这一点只能使用一个tour_id连接列?

0 个答案:

没有答案