1

I am struggling with my inheritance structure where I have a mapped superclass which contains a common field in the concrete classes. This superclass has a one-to-one mapping with a "wrapper" object.

The objects look like this;

@Entity
public class Wrapper {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "wrapper_id", nullable = false)
    private Long wrapperId;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "wrapper")
    @Cascade(CascadeType.SAVE_UPDATE)
    private Base base;

    public Long getWrapperId() {
        return wrapperId;
    }

    public void setWrapperId(Long wrapperId) {
        this.wrapperId = wrapperId;
    }

    public Base getBase() {
        return base;
    }

    public void setBase(Base base) {
        this.base = base;
    }

}

@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Base {

    @OneToOne(fetch = FetchType.LAZY)
    @Cascade(CascadeType.SAVE_UPDATE)
    @JoinColumn(name = "wrapper_id")
    protected Wrapper wrapper;

    public Wrapper getWrapper() {
        return wrapper;
    }

    public void setWrapper(Wrapper wrapper) {
        this.wrapper = wrapper;
    }

}

@Entity
public class SubA extends Base {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "sub_a_id", nullable = false)
    private Long subAId;

    public Long getSubAId() {
        return subAId;
    }

    public void setSubAId(Long subAId) {
        this.subAId = subAId;
    }

}

For simplicity I have only included a single concrete class but I have several.

This mapping works great when I do not have a reference to "Base" in the wrapper object. As soon as I try to add the bi-directional relationship between the wrapper and base I start to get this error....which doesn't make sense as the field is there.

Caused by: org.hibernate.AnnotationException: Unknown mappedBy in: com.xxx.Wrapper.base, referenced property unknown: com.xxx.Base.wrapper
    at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:153)
    at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:453)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:438)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1627)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1564)
    ... 50 more

What am I missing? Thanks,

gwnp
  • 1,127
  • 1
  • 10
  • 35

3 Answers3

3

Quote from Java Platform, Enterprise Edition: The Java EE Tutorial:

37.2.2 Mapped Superclasses

Entities may inherit from superclasses that contain persistent state and mapping information but are not entities. That is, the superclass is not decorated with the @Entity annotation and is not mapped as an entity by the Java Persistence provider. These superclasses are most often used when you have state and mapping information common to multiple entity classes. Mapped superclasses are specified by decorating the class with the annotation javax.persistence.MappedSuperclass:

...

Mapped superclasses cannot be queried and cannot be used in EntityManager or Query operations. You must use entity subclasses of the mapped superclass in EntityManager or Query operations. Mapped superclasses can't be targets of entity relationships.

So it looks like you can`t use this Base class in entity relationships:

@OneToOne(fetch = FetchType.LAZY, mappedBy = "wrapper")
@Cascade(CascadeType.SAVE_UPDATE)
private Base base;
Community
  • 1
  • 1
bary
  • 1,699
  • 2
  • 15
  • 24
0

Looks like this hibernate bug: Hibernate complains about an unknown mappedBy property when mapping a bidirectional OneToOne relation with a derived identifier, which was fixed only in late hibernate 4.2.2, 4.3.0.Beta3 versions.

Andremoniy
  • 34,031
  • 20
  • 135
  • 241
0

We ended up doing a lot of prototyping with the different options (mapped super class, hierarchical etc) and weighed the options.

In the end we decided to create object hierarchies coupled with the @Entity annotation, Inheritance strategy of SINGLE_TABLE and using Discriminator values to give us exactly what we needed without sacrificing too much.

Thank you all for your suggestions.

gwnp
  • 1,127
  • 1
  • 10
  • 35