问题描述
这是参考这个。
This is in reference to this answer.
Entities-
// Many to One
@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
One to Many
@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 file-
<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>
the persistence logic-
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();
I am getting -
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)
It works perfect with hbms.
Please suggest.
Thanks Vlad and Neil, it works but there is a problem described below-
This is the structure which gets created with HBMs. Hence the same must be with 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 )
the moment I do -
@OneToMany(cascade = CascadeType.ALL, mappedBy = "person") private Set<Address> addSet = new HashSet<Address>();
the join table structure is-
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 )
You see that the primary key is NOT a combination of addressid and personid as in HBMs. Please suggest.
You need to add a cascade the one-to-many side:
@OneToMany(cascade = CascadeType.ALL)
Check out this article for more details.
Then, change the @ManyToOne side to:
@ManyToOne @JoinTable(name="PersonAddress", joinColumns=@JoinColumn(name="addressId"), inverseJoinColumns=@JoinColumn(name="personId") ) private Person person;
and the @OneToMany side to:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "person") private Set<Address> addSet = new HashSet<Address>();
Update
To address the composite-key requirement as indicated by the question update, try mapping the join table (e.g. personaddress) as an entity, and use composite keys as explained in this article.
这篇关于与JPA注解的双向@OneToMany关系似乎不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!