Hibernate继承问题

时间:2018-01-09 20:57:13

标签: java hibernate

我遇到了Hibernate继承问题。我一直试图找出导致异常的原因。我得到的例外是

  

引起:java.lang.ClassCastException:org.hibernate.mapping.SingleTableSubclass无法强制转换为org.hibernate.mapping.RootClass。

完整的例外情况可以在本文末尾找到。

public interface PersistentObjectKey {
    public String getPromotionId();

    public Integer getVersion();
}

//促销

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "promotion")
public abstract class Promo implements PersistentObjectKey{
    @Id
    @Column(name="promotionId")
    @GeneratedValue(strategy=GenerationType.AUTO)
    protected String promotionId;


    @OneToMany(mappedBy="promo", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
    @NotNull
    protected Set<Product> product = new HashSet<Product>();

    @Embedded
    @NotNull
    protected Attribute attribute;

    @Embedded
    @NotNull
    protected Duration duration; 

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name="imageTitle", column=@Column(nullable=true)),
        @AttributeOverride(name="imageFileName", column=@Column(nullable=true)),
        @AttributeOverride(name="imageUrl", column=@Column(nullable=true))
    })
    private Image promoImage; 



    @Embedded
    @Column(nullable=true)
    protected TermsAndConditions termsAndConditions;

    protected Promo(){
    }

    public static class PromoBuilder{

        private Set<Product> product;
        private Attribute attributes;
        private Duration duration;


        private TermsAndConditions termsAndConditions;
        private Image promoImage;

        public PromoBuilder(Set<Product> product, Attribute attributes, Duration duration){
            this.product = product;
            this.attributes = attributes;
            this.duration = duration;
        }

        public PromoBuilder termsAndConditions(TermsAndConditions termsAndConditions){
            this.termsAndConditions = termsAndConditions;
            return this;
        }

        public PromoBuilder promoImage(Image promoImage){
            this.promoImage = promoImage;
            return this;
        }

        public Promo build(){
            return null;
        }
    }


    protected Promo(PromoBuilder promoBuilder){
        this.product = promoBuilder.product;
        this.attribute = promoBuilder.attributes;
        this.duration = promoBuilder.duration;
        this.termsAndConditions = promoBuilder.termsAndConditions;
        this.promoImage = promoBuilder.promoImage;
    } 

    protected PromoBuilder newBuilder(){
        return new PromoBuilder(getProduct(), getAttribute(), getDuration());
    }

    protected PromoBuilder decorate(PromoBuilder builder){
        return builder.termsAndConditions(getTermsAndConditions());
    }

    public PromoBuilder toBuilder(){
        return decorate(newBuilder());
    }


    public String getPromotionId() {
        return promotionId;
    }

    public Integer getVersion() {
        return 10;
    }

    public Set<Product> getProduct() {
        return product;
    }
    public void setProduct(Set<Product> product) {
        this.product = product;
    }

    public Attribute getAttribute() {
        return attribute;
    }
    public void setAttribute(Attribute attribute) {
        this.attribute = attribute;
    }

    public Duration getDuration() {
        return duration;
    }
    public void setDuration(Duration duration) {
        this.duration = duration;
    }

    public Image getPromoImage() {
        return promoImage;
    }
    public void setPromoImage(Image promoImage) {
        this.promoImage = promoImage;
    }

    public TermsAndConditions getTermsAndConditions() {
        return termsAndConditions;
    }
    public void setTermsAndConditions(TermsAndConditions termsAndConditions) {
        this.termsAndConditions = termsAndConditions;
    }

    public boolean equals(Object o){
        if(this == o){
            return true;
        }
        if(o == null || !(o instanceof PersistentObjectKey)){
            return false;
        }
        PersistentObjectKey other = (PersistentObjectKey)o;
        // if the id is missing, return false
        if(this.promotionId == null){
            return false;
        }

        return this.promotionId.equals(other.getPromotionId());
    }

    public int hashCode(){
        if(promotionId != null){
            return promotionId.hashCode();
        }else{
            return super.hashCode();
        }
    }

    public String toString() {
        return this.getClass().getName()
            + "[id=" + promotionId + "]";
    }
}

//优惠券

@Entity
@Table(name = "coupon")
@PrimaryKeyJoinColumn(name="couponId", referencedColumnName="promotionId")
public class Coupon extends Promo{

    @Column(name="onlineCode", nullable=true)
    @Pattern(regexp="[a-zA-Z0-9]+", message="LATER")  
    private String onlineCode = "";

    @Column(name="offlineCode",nullable=true)
    private String offlineCode = "";

    protected Coupon(){}

    private Coupon(CouponBuilder couponBuilder){
        super(couponBuilder);
        this.onlineCode= couponBuilder.onlineCode;
        this.offlineCode = couponBuilder.offlineCode;
    }

    public class CouponBuilder extends Promo.PromoBuilder{
        private String onlineCode = "";
        private String offlineCode = "";

        public CouponBuilder(Set<Product> product, Attribute attributes, Duration duration){
            super(product, attributes, duration);
        }

        public CouponBuilder onlineCode(String onlineCode){
            this.onlineCode = onlineCode;
            return this;
        }

        public CouponBuilder offlineCode(String offlineCode){
            this.offlineCode = offlineCode;
            return this;
        }

        @Override
        public CouponBuilder termsAndConditions(TermsAndConditions termsAndConditions){
            return (CouponBuilder) super.termsAndConditions(termsAndConditions);
        }

        @Override
        public CouponBuilder promoImage(Image promoImage){
            return (CouponBuilder)super.promoImage(promoImage);
        }



        public Coupon build(){
            switch(attribute.getPromoUsage()){
            case ONLINE:
                if(this.onlineCode.equalsIgnoreCase("")){
                    throw new IllegalArgumentException("You must enter online coupon code");
                }
            case OFFLINE:
                if(this.offlineCode.equalsIgnoreCase("")){
                    throw new IllegalArgumentException("You must enter instore coupon code");
                }
            case ONLINE_AND_OFFLINE:
                if(this.onlineCode.equalsIgnoreCase("") || this.offlineCode.equalsIgnoreCase("")){
                    throw new IllegalArgumentException("You must enter online and instore code");
                }
            }
            return new Coupon(this);
        }
    }

    // GETTERS AND SETTERS

    public String getOnlineCode() {
        return onlineCode;
    }
    public void setOnlineCode(String onlineCode) throws IllegalArgumentException{
        if(onlineCode.equals("")){
            throw new IllegalArgumentException("code cannot be empty");
        }
        this.onlineCode = onlineCode;
    }

    public String getOfflineCode() {
        return offlineCode;
    }
    public void setOfflineCode(String offlineCode) throws IllegalArgumentException{
        if(offlineCode.equals("")){
            throw new IllegalArgumentException("code cannot be empty");
        }
        this.offlineCode = offlineCode;
    }


}

//产品

@Entity
@Table(name="product")
public class Product {


    @Id
    @Column(name="productId")
    private String productId = IdGenerator.createId(); 


    @Column(name="productName", nullable=false)
    @NotNull
    private String name;


    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="categoryId", nullable=false) 
    @NotNull
    private Category category;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="promotionId", nullable=true)
    @JsonBackReference
    private Promo promo;


    @Column(name="price", nullable=true)
    private double price;

    @Column(name="discountPercentage", nullable=false)
    private int discountPercentage;


    @ElementCollection
    @CollectionTable(
            name="image",
            joinColumns = @JoinColumn(name="productId"))
    private Set<Image> images = new HashSet<Image>(); 


    public Product(){
    }

    private Product(ProductBuilder productBuilder) {
        this.name = productBuilder.name;
        this.category = productBuilder.category;
        this.price = productBuilder.price;
        this.discountPercentage = productBuilder.discountPercentage;
        this.images = productBuilder.images;
    }

    public static class ProductBuilder{ 

        private String name;


        private Category category;


        private double price = 0f;
        private int discountPercentage = 0;

        @OneToMany 
        private Set<Image> images = new HashSet<>(); 


        public ProductBuilder(String name, Category category){
            this.name = name;
            this.category = category;
        }

        public ProductBuilder price(double price){
            this.price = price;
            return this;
        }

        public ProductBuilder discountPercentage(int discountPercentage){
            this.discountPercentage = discountPercentage;
            return this;
        }

        public ProductBuilder images(Set<Image> images){
            this.images = images;
            return this;
        }

        public Product build(){
            return new Product(this);
        }
    }

    // GETTERS AND SETTERS
    public String getProductId() {
        return productId;
    }

    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }

    public double getDiscountPercentage() {
        return discountPercentage;
    }

    public void setDiscountPercentage(int discountPercentage) throws IllegalArgumentException{
        if(discountPercentage <= 0){ 
            throw new IllegalArgumentException("Discount percentage cannot be zero or negative");
        }
        this.discountPercentage = discountPercentage;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Category getCategory() {
        return category;
    }
    public void setCategory(Category category) {
        this.category = category;
    }

    public Set<Image> getImages() {
        return images;
    }
    public void setImages(Set<Image> images) {
        this.images = images;
    }

    @Override
    public boolean equals(Object o){
        if(this == o){
            return true;
        }
        if(o == null || !(getClass() == o.getClass())){
            return false;
        }
        Product other = new Product();

        return Objects.equals(name, other.name) && Objects.equals(category,other.category) && 
                Objects.equals(price, other.price) && Objects.equals(discountPercentage, other.discountPercentage) &&
                Objects.equals(images, other.images);
    }

    public int hashCode(){
        if(productId != null){
            return productId.hashCode();
        }else{
            return super.hashCode();
        }
    }


}

//属性

@Embeddable
public class Attribute {

    @Column(name="shortDescription", nullable=false)
    @NotNull
    protected String shortDescription;

    @Column(name="detailDescription", nullable=true)
    protected String detailDescription;


    @Column(name="promoUsage", nullable=false) 
    @NotNull
    @Enumerated(EnumType.STRING)
    private PromoUsage promoUsage;  

    @Column(name="destinationUrl", nullable=true)
    protected String destinationUrl;

    public Attribute(){}

    private Attribute(AttributesBuilder attributesBuilder){
        this.shortDescription = attributesBuilder.shortDescription;
        this.destinationUrl = attributesBuilder.destinationUrl;
        this.promoUsage = attributesBuilder.promoUsageType;
        this.detailDescription = attributesBuilder.detailDescription;
    }

    public static class AttributesBuilder{
        private String shortDescription;
        private String detailDescription;
        private PromoUsage promoUsageType;
        private String destinationUrl;

        //Builder constructor
        public AttributesBuilder(String shortDescription, PromoUsage promoUsageType){
            this.shortDescription = shortDescription;
            this.promoUsageType = promoUsageType;
        }

        public AttributesBuilder detailDescription(String detailDescription){
            this.detailDescription = detailDescription;
            return this;
        }

        public AttributesBuilder destinationUrl(String destinationurl){
            this.destinationUrl = destinationurl;
            return this;
        }

        public Attribute build()throws IllegalArgumentException{
            if(this.promoUsageType == PromoUsage.ONLINE || this.promoUsageType == PromoUsage.ONLINE_AND_OFFLINE){
                if(destinationUrl.equals("")){ 
                    throw new IllegalArgumentException("destination Url must not be empty");
                }
            }
            if(this.shortDescription == null || this.shortDescription.equals("")){
                throw new IllegalArgumentException("Please provide a short description for the promo");
            }

            return new Attribute(this);
        }
    }



    public String getShortDescription() {
        return shortDescription;
    }
    public void setShortDescription(String shortDescription) {
        this.shortDescription = shortDescription;
    }

    public String getDetailDescription() {
        return detailDescription;
    }
    public void setDetailDescription(String detailDescription) {
        this.detailDescription = detailDescription;
    }

    public PromoUsage getPromoUsage() {
        return promoUsage;
    }
    public void setPromoUsage(PromoUsage promoUsage) {
        this.promoUsage = promoUsage;
    }

    public String getDestinationUrl() {
        return destinationUrl;
    }
    public void setDestinationUrl(String destinationUrl) {
        this.destinationUrl = destinationUrl;
    }

    public boolean equals(Object o){
        return false;
    } 

    public int hashCode(){
        return 1;
    }

}

//持续时间

@Embeddable
public class Duration {


    @Column(name="startDate", nullable=false)
    @NotNull
    @JsonFormat(pattern = "dd-MM-YYYY")
    private Date startDate;


    @Column(name="expirationDate", nullable=false)
    @NotNull
    @JsonFormat(pattern = "dd-MM-YYYY")
    private Date expirationDate;

    public Duration(){
    }

    public Duration(Date startDate, Date expirationDate){
        this.startDate = startDate;
        this.expirationDate = expirationDate;
    }

    public Date getStartDate() {
        return startDate;
    }
    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getExpirationDate() {
        return expirationDate;
    }
    public void setExpirationDate(Date expirationDate) {
        this.expirationDate = expirationDate;
    }

    public boolean equals(Object o){
        return false;
    } 

    public int hashCode(){
        return 1;
    }
}

//类别

@Entity
@Table(name="category")
public class Category {

    @Id
    @Column(name="categoryId")
    private String categoryId = IdGenerator.createId();

    @Column(nullable=false, unique=true)
    @Size(min=2, max=60, message="LATER")
    private String categoryName;

    public Category() {

    }

    public String getCategoryId() {
        return categoryId;
    }

    public String getCategoryName() {
        return categoryName;
    }
    public void setCategoryName(String categoryName) {
        this.categoryName = categoryName;
    }
}

//图片

@Entity
public class Image extends MediaFile{

    public Image(){}

    public Image(String title, String fileName, String url) {
        super(title, fileName, url);
    }


}


public enum PromoUsage {

    ONLINE, OFFLINE, ONLINE_AND_OFFLINE;
}

//异常:(由于Stack Overflow上的字符限制,我只能发布部分内容)

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/grabone/utility/GrabOneConfiguration.class]: Invocation of init method failed; nested exception is java.lang.ClassCastException: org.hibernate.mapping.SingleTableSubclass cannot be cast to org.hibernate.mapping.RootClass
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 28 common frames omitted
Caused by: java.lang.ClassCastException: org.hibernate.mapping.SingleTableSubclass cannot be cast to org.hibernate.mapping.RootClass
    at org.hibernate.cfg.annotations.PropertyBinder.bind(PropertyBinder.java:208) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:199) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2225) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.fillComponent(AnnotationBinder.java:2635) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.fillComponent(AnnotationBinder.java:2522) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.bindComponent(AnnotationBinder.java:2470) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2185) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:911) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:738) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:245) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 38 common frames omitted

1 个答案:

答案 0 :(得分:0)

版本4.2.2中存在一个Hybernate问题,它从未解决,看起来像您的例外: https://hibernate.atlassian.net/browse/HHH-8307

此外,我发现了一个类似于stackoverflow的问题。 也许它有帮助: Spring 3.1 Hibernate 4 exception for Inheritance [cannot be cast to org.hibernate.mapping.RootClass]

祝你好运!