【问题标题】:Two problems in a @OneToOne relationship@OneToOne 关系中的两个问题
【发布时间】:2020-01-05 03:44:50
【问题描述】:

我使用的是 Hibernate 4.3.6.Final 和 WildFly 16。@OneToOne 关系存在两个问题。

1.) 第一个问题:Unknown mappedBy in: at.home.digest.model.Expose.home,引用属性未知: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;

    }

现在我不再面临第一个问题了。但是,当保存主实体时,它不再引用相应的公开实体。相反,SQL 表 home 中的 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);
    }
}

具有相应公开实体的 Home 实体在不引用相应公开实体的情况下被保存,即 home 表中的 Expose_id 列为空。但是,相应的暴露实体与对主实体的引用一起保存,即暴露表中的列 home_id 正确地引用了主表中的相应行。

【问题讨论】:

  • 您是否尝试过在 Home 实体中不使用 mappedBy
  • @ConstantinBeer 是的,请看我上面的源代码
  • 我不是指Expose 中的mappedBy。我的意思是在您的Home 实体中,mappedBy="home"
  • @ConstantinBeer 在我的 Home 实体中,我有 fetch = FetchType.LAZY, mappedBy = "home", cascade = CascadeType.ALL
  • @ConstantinBeer 谢谢!我会检查并告诉你。亲切的问候:亚历克斯

标签: hibernate cascade one-to-one bidirectional-relation hibernate-cascade


【解决方案1】:

我无法完全解释错误在哪里。但是,我解决了如下问题:

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

2.) 当我使用 MySQL Server 5.7 时,我需要将我的 persistence.xml 中的 Hibernate Dialect 更改为

org.hibernate.dialect.MySQL57Dialect 

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

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 现在共享一个相同的主键,这对提高效率很重要。我的 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);
    }

【讨论】:

    猜你喜欢
    • 2019-10-17
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    相关资源
    最近更新 更多