【问题标题】:Bidirectional @OneToMany relation with JPA annotations doesn't seem to work与 JPA 注释的双向 @OneToMany 关系似乎不起作用
【发布时间】:2017-05-22 06:59:29
【问题描述】:

这是指answer

实体-

// 多对一

@Entity
@Table
public class Address {

    @Id
    @GeneratedValue
    @Column
    private int addressIdentity;

    @Column
    private int houseNo;

    @Column
    private char streetNo;

    @Column
    private int pincode;

    @Column
    private String city;

    @Column
    private String state;

    @Column
    private String country;

    @ManyToOne
       @JoinTable(name="PersonAddress", 
            joinColumns=@JoinColumn(name="addressId", insertable = false, updatable = false),
            inverseJoinColumns=@JoinColumn(name="personId", insertable = false, updatable = false)
       )
    private Person person;
    // getters and setters

一对多

@Entity
@Table
public class Person {

    @Id
    @GeneratedValue
    @Column
    private int personId;

    @Column
    private String name;

    @Column
    private String designation;

    @OneToMany
    @JoinTable(name = "PersonAddress", 
                            joinColumns = @JoinColumn(name = "personId"), 
                                inverseJoinColumns = @JoinColumn(name = "addressId"))
    private Set<Address> addSet = new HashSet<Address>();
    // getters and setters


休眠配置文件-
<hibernate-configuration>
    <session-factory name="">
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.password">hello</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/xyz</property>
        <property name="hibernate.connection.username">postgres</property>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">create</property>
        <mapping class="ManyToOne_OneToManyMappingWithJoinTable.Person" />
        <mapping class="ManyToOne_OneToManyMappingWithJoinTable.Address" />
    </session-factory>
</hibernate-configuration>

持久化逻辑-

        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        Person person1 = new Person();
        person1.setName("Shahnaz Parveen");
        person1.setDesignation("HouseWife");

        Address address1 = new Address();
        address1.setHouseNo(18);
        address1.setStreetNo('E');
        address1.setPincode(250002);
        address1.setCity("Meerut");
        address1.setState("UP");
        address1.setCountry("INDIA");
        address1.setPerson(person1);

        Address address2 = new Address();
        address2.setHouseNo(84);
        address2.setStreetNo('1');
        address2.setPincode(250002);
        address2.setCity("Meerut");
        address2.setState("UP");
        address2.setCountry("INDIA");
        address1.setPerson(person1);

        person1.getAddSet().add(address1);
        person1.getAddSet().add(address2);

        session.save(address1);
        session.save(address2);
        session.save(person1);

        session.getTransaction().commit();
        session.close();


我正进入(状态 -
Jan 07, 2017 9:47:35 PM org.hibernate.action.internal.UnresolvedEntityInsertActions logCannotResolveNonNullableTransientDependencies
WARN: HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.
    Unsaved transient entity: ([ManyToOne_OneToManyMappingWithJoinTable.Person#0])
    Dependent entities: ([[ManyToOne_OneToManyMappingWithJoinTable.Address#1]])
    Non-nullable association(s): ([ManyToOne_OneToManyMappingWithJoinTable.Address.person])
Exception in thread "main" org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved beforeQuery current operation : ManyToOne_OneToManyMappingWithJoinTable.Address.person -> ManyToOne_OneToManyMappingWithJoinTable.Person
    at org.hibernate.action.internal.UnresolvedEntityInsertActions.checkNoUnresolvedActionsAfterOperation(UnresolvedEntityInsertActions.java:122)
    at org.hibernate.engine.spi.ActionQueue.checkNoUnresolvedActionsAfterOperation(ActionQueue.java:418)
    at org.hibernate.internal.SessionImpl.checkNoUnresolvedActionsAfterOperation(SessionImpl.java:621)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:684)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:674)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:669)
    at ManyToOne_OneToManyMappingWithJoinTable.ManyToOne_OneToManyMappingWithJoinTableImpl.main(ManyToOne_OneToManyMappingWithJoinTableImpl.java:40)

它与 hbms 完美搭配。

请提出建议。


感谢 Vlad 和 Neil,它可以工作,但存在如下所述的问题-

这是使用 HBM 创建的结构。因此,注释也必须如此。

CREATE TABLE person_address
(
  addressid integer NOT NULL,
  personid integer NOT NULL,
  CONSTRAINT person_address_pkey PRIMARY KEY (addressid , personid ),
  CONSTRAINT fkkpp6mysmnyiywx3q33yxr1gbe FOREIGN KEY (personid )
      REFERENCES person (person_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fkrpk0jx2y558su288tx9kd5cs6 FOREIGN KEY (addressid )
      REFERENCES address (address_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

我做的那一刻 -

@OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private Set<Address> addSet = new HashSet<Address>();

连接表结构是-

CREATE TABLE personaddress
(
  personid integer,
  addressid integer NOT NULL,
  CONSTRAINT personaddress_pkey PRIMARY KEY (addressid),
  CONSTRAINT fkfd5pm843bldj10y5kxwo37xge FOREIGN KEY (addressid)
      REFERENCES address (addressidentity) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fkjuwlthwsi53bpf902nnl6snxh FOREIGN KEY (personid)
      REFERENCES person (personid) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

您会看到主键不像 HBM 中那样是 addressid 和 personid 的组合。请提出建议。

【问题讨论】:

  • 不存在双向关系。为此,您需要“mappedBy”
  • @NeilStockton:放在哪里。请提出建议。
  • 为什么不把它放在@OneToMany 注释中,就像互联网上的文档页面告诉你的那样
  • @NeilStockton:那么它就不会是一个连接表了。
  • 这被称为您的 JPA 提供程序中的错误,您应该报告。

标签: java hibernate jpa orm hibernate-mapping


【解决方案1】:

您需要在一对多端添加级联:

@OneToMany(cascade = CascadeType.ALL)

然后,将@ManyToOne 一侧更改为:

@ManyToOne
@JoinTable(name="PersonAddress", 
    joinColumns=@JoinColumn(name="addressId"),
    inverseJoinColumns=@JoinColumn(name="personId")
)
private Person person;

@OneToMany 方:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private Set<Address> addSet = new HashSet<Address>();

要解决问题更新所指示的复合键要求,请尝试将连接表(例如personaddress)映射为实体,并使用composite identifiers

【讨论】:

  • 同样的异常仍然存在。请提出建议。
  • 尝试将 @Id 从 int 更改为 Integer
  • 使用包装类后也出现同样的异常。
  • 由于映射是双向的,因此异常提示 - 在保存这些依赖实体之前,必须将未保存的瞬态实体保存在操作中。可以清楚地看到,两者都是 PERSON 和 ADDRESS 实体是相互交叉依赖的。这是一个僵局。异常发生在 - session.save(address1); 之前 session.save(address2); session.save(person1); 任何建议。
  • 感谢弗拉德,我能够通过复合键实现连接表结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 1970-01-01
  • 2017-06-23
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多