与JPA注解的双向@OneToMany关系似乎不起作用 [英] Bidirectional @OneToMany relation with JPA annotations doesn't seem to work
问题描述
这是参考这个 实体 - //多对一
@Entity
@Table
公共类地址{
@Id
@GeneratedValue
@Column
private int addressIdentity;
@Column
private int houseNo;
@Column
private char streetNo;
@Column
private int pincode;
@Column
私人字符串城市;
@Column
私有字符串状态;
@Column
私人字符串国家;
@ManyToOne
@JoinTable(name =PersonAddress,
joinColumns = @ JoinColumn(name =addressId,insertable = false,updatable = false),
)joinJoinColumns = @ 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
私人字符串名称;
@Column
私人字符串指定;
$ b @OneToMany
@JoinTable(name =PersonAddress,
joinColumns = @JoinColumn(name =personId),
inverseJoinColumns = @JoinColumn(name = addressId))
private Set< Address> addSet = new HashSet< Address>();
// getters和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>建立< / 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);
地址address1 =新地址();
address1.setHouseNo(18);
address1.setStreetNo('E');
address1.setPincode(250002);
address1.setCity(Meerut);
address1.setState(UP);
address1.setCountry(INDIA);
address1.setPerson(person1);
地址address2 =新地址();
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();
我得到 -
'pre>
2017年1月7日下午九时47分35秒org.hibernate.action.internal.UnresolvedEntityInsertActions logCannotResolveNonNullableTransientDependencies
WARN:HHH000437:试图保存一个或多个实体与未保存的瞬态实体具有不可空的关联。未保存的瞬态实体必须在保存这些从属实体之前保存在操作中。
未保存的临时实体:([ManyToOne_OneToManyMappingWithJoinTable.Person#0])
从属实体:([[ManyToOne_OneToManyMappingWithJoinTable.Address#1]])
不可为空的关联(S):([ManyToOne_OneToManyMappingWithJoinTable .Address.person])在螺纹
异常主 org.hibernate.TransientPropertyValueException:非空属性引用瞬态值 - 瞬态的实例必须保存beforeQuery当前操作: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)
。在org.hibernate.internal.SessionImpl.checkNoUnresolvedActionsAfterOperation(SessionImpl.java:621)
处org.hibernate作为org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:684)
。在许多OneToManyMappingWithJoinTable.ManyToOne_OneToManyMappingWithJoinTableImpl.main(ManyToOne_OneToManyMappingWithJoinTableImpl.java:40)
(org.hibernate.internal.SessionImpl.save(SessionImpl.java:669))
(SessionImpl.java:674)
它适用于hbms。
请建议。
感谢Vlad和Neil,它可以工作,但是有一个问题 -
这是用HBM创建的结构。
CREATE TABLE person_address
(
addressid integer NOT NULL,
PERSONID整数NOT NULL,
约束person_address_pkey PRIMARY KEY(addressid,PERSONID),
约束fkkpp6mysmnyiywx3q33yxr1gbe外键(PERSONID)
参考人(为person_id)MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
约束fkrpk0jx2y558su288tx9kd5cs6外键(addressid)
参考地址(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>();
连接表结构是 -
<$ p
personid integer,
addressid integer NOT NULL,
CONSTRAINT personaddress_pkey PRIMARY KEY(addressid),
CONSTRAINT (personid)
REFERENCES person(personid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
您会看到主键不像HBM中的 addressid和personid 的组合。请提出建议。
您需要添加级联的一对多方:
@OneToMany(cascade = CascadeType.ALL)
查看这篇文章
$ b
然后,将 @ManyToOne
一边更改为:
@ManyToOne
@JoinTable(name =PersonAddress,
joinColumns = @ JoinColumn(name =addressId),
reverseJoinColumns = @ JoinColumn(name =personId)
)
私人person person;
和 @OneToMany
/ p>
@OneToMany(cascade = CascadeType.ALL,mappedBy =person)
private Set< Address> addSet = new HashSet< Address>();
更新
如问题更新所示,请尝试将连接表(例如 personaddress
)映射为实体,并使用复合键,如本文。
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关系似乎不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!