@OneToOne 关系中的两个问题

Two problems in a @OneToOne relationship

我正在使用 Hibernate 4.3。6.Final 和 WildFly 16。@OneToOne 关系有两个问题。

1.) 第一个问题:Unknown mappedBy in: at.home.digest.model.Expose.home, referenced 属性 unknown: at.home.digest.model.Home.expose"}}

这些是我的实体:

@Entity
@Table(name = "home",
    uniqueConstraints =  @UniqueConstraint (columnNames = {"URL"})
)
@Access(AccessType.FIELD)
public class Home implements Serializable { 

    @OneToOne (fetch = FetchType.LAZY, mappedBy = "home", cascade = CascadeType.ALL)
    @JoinColumn(name = "expose_id")
    private Expose expose;

    public Expose getExpose() {
        return expose;
    }

    public void setExpose(Expose expose) {
        this.expose = expose;
    }
    ................

}

公开实体:

@Entity
@Table(name ="expose")
@Access(AccessType.FIELD)
public class Expose  implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id", updatable=false, nullable=false)
    private int id; 

    @OneToOne (fetch = FetchType.EAGER, mappedBy = "expose", cascade=CascadeType.PERSIST )
    @JoinColumn(name = "home_id")
    private Home home;

    @ManyToOne ( optional = false, cascade=CascadeType.MERGE )
    @JoinColumn(name = "contact_id")
    private Contact contact;

}

部署应用程序后,我收到:

Caused by: org.hibernate.AnnotationException: Unknown mappedBy in: at.home.digest.model.Expose.home, referenced property unknown: at.home.digest.model.Home.expose"}}

2.) 第二个问题:首先,我通过从 Expose 实体中删除属性 mappedBy = "expose" 克服了第一个问题,即 Expose 实体现在看起来像:

@Entity
@Table(name ="expose")
@Access(AccessType.FIELD)
public class Expose  implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id", updatable=false, nullable=false)
    private int id; 


    @OneToOne (fetch = FetchType.EAGER, cascade=CascadeType.PERSIST )
    @JoinColumn(name = "home_id")
    private Home home;

    @ManyToOne ( optional = false, cascade=CascadeType.MERGE )
    @JoinColumn(name = "contact_id")
    private Contact contact;

    }

现在我不再面临第一个问题了。但是,在保存 home 实体时,它不再引用相应的公开实体。相反,SQL table 主页中的字段 expose_id 为空。:

这是我保存实体的源代码:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void saveEntity(Home home) throws EntityExistsException {

    Expose expose = null;
    if (home.getExpose() != null && home.getExpose().getContact() != null) {
        Contact contact = this.em.merge(home.getExpose().getContact());
        home.getExpose().setContact(contact);
        expose = this.em.merge(home.getExpose());
        home.setExpose(expose);
    }
    this.em.persist(home);
    if (expose != null) {
        expose.setHome(home);
        expose = this.em.merge(expose);
        home.setExpose(expose);
        this.em.merge(home);
    }
}

具有相应公开实体的主页实体在没有引用相应公开实体的情况下被保存,即主页 table 中的 expose_id 列为空。相应的公开实体保存时引用了 home 实体,即公开 table 中的列 home_id 正确引用了 home table.[=15= 中的相应行]

我不能完全解释错误在哪里。不过,我是这样解决问题的:

1.) 我将 MySQL 数据库保存在一个文件中(使用 mysqldump),然后删除了整个数据库。

2.) 由于我使用的是 MySQL Server 5.7,因此我需要将 persistence.xml 中的 Hibernate Dialect 更改为

org.hibernate.dialect.MySQL57Dialect 

(之前是 org.hibernate.dialect.MySQLDialect)。我还将 属性 hibernate.hbm2ddl.auto 设置为 create 以便休眠在下一次部署应用程序时重新创建我的所有表

3.) 我按照此处的文章更改了 Home 和 Expose 之间的休眠 @OneToOne 映射:

https://hellokoding.com/jpa-one-to-one-shared-primary-key-relationship-mapping-example-with-spring-boot-maven-and-mysql/

通过这种方式,Expose 和 Home 现在共享同一个主键,这有助于提高效率。 My Home 和 Expose 实体现在如下:

@Entity
@Table(name = "home",
    uniqueConstraints =  @UniqueConstraint (columnNames = {"URL"})
)
@Access(AccessType.FIELD)
public class Home implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id; 


    @OneToOne (fetch = FetchType.LAZY,  mappedBy = "home", cascade = CascadeType.ALL)
    private Expose expose;

    // ..... setters and getters here

}

@Entity
@Table(name ="expose")
@Access(AccessType.FIELD)
public class Expose  implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    private int id; 

    @OneToOne (fetch = FetchType.LAZY)
    @JoinColumn (name = "id")
    @MapsId
    private Home home;

        // ..... setters and getters here

}

4.) 保存家庭实体的代码现在如下所示:

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void updateEntityWithExpose(Home home) throws EntityExistsException {
        Expose expose = null;
        if (home.getExpose() != null && home.getExpose().getContact() != null) {
            Contact contact = this.em.merge(home.getExpose().getContact());
            home.getExpose().setContact(contact);
        }
        this.em.persist(home);
    }