与JPA注释的双向@OneToMany关系似乎不起作用

时间:2017-01-07 16:50:30

标签: java hibernate jpa orm hibernate-mapping

这是参考此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配置文件 -

<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创建的结构。因此,必须使用Annotations。

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 的组合。请建议。

1 个答案:

答案 0 :(得分:3)

您需要添加一对多的级联:

@OneToMany(cascade = CascadeType.ALL)

查看this article了解详情。

然后,将@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)映射为实体,并使用复合键,如this article中所述。