我确信这个问题之前已经被问过了,但我似乎无法找到答案。我正在使用Hibernate 4.0做一个基本的关系。我有一个Person对象可以包含可能的地址(是的,从另一个网站得到的代码认为它会工作,但事实并非如此)。我想要使用连接表。我觉得我已经尝试了所有可能的组合,但不断提出相同的错误:“对于键1,重复输入”1-3“。基本上,当我在设置双方关系(人员/地址)后尝试提交事务时发生Hibernate错误。很明显,它试图插入相同的记录两次,这是连接表上不允许的,因为personId/addressId组合应该只出现一次。任何帮助将不胜感激,一个有效的Junit测试也许。在下面我手动插入一个人和三个地址,前两个已经与该人有关。休眠一对多连接表 - 重复插入
1)我是否必须明确设置双方的关系(人员和地址)?似乎不正确,因为其他对象之一会不同步。 2)为什么这个工作正常,如果我使用List而不是Set?
单元测试:
@Test
public void tryAgain(){
Person p = em.find(Person.class, 1);<br>
Address a = em.find(Address.class, 1);<br>
Address b= em.find(Address.class,2);<br>
Address c= em.find(Address.class, 3);<br>
em.getTransaction().begin();<br>
p.addresses.add(c);<br>
c.person=p;<br>
em.getTransaction().commit();<br>
assertTrue(p.addresses.size()==3);<br>
}
JUnit的堆栈跟踪
Hibernate: select person0_.personId as personId3_0_ from PERSON person0_ where person0_.personId=?
<br>Hibernate: select address0_.addressId as addressId6_1_, address0_1_.personId as personId7_1_, person1_.personId as personId3_0_ from ADDRESS address0_ left outer join PersonAddress address0_1_ on address0_.addressId=address0_1_.addressId left outer join PERSON person1_ on address0_1_.personId=person1_.personId where address0_.addressId=?
<br>Hibernate: select address0_.addressId as addressId6_1_, address0_1_.personId as personId7_1_, person1_.personId as personId3_0_ from ADDRESS address0_ left outer join PersonAddress address0_1_ on address0_.addressId=address0_1_.addressId left outer join PERSON person1_ on address0_1_.personId=person1_.personId where address0_.addressId=?
<br>Hibernate: select address0_.addressId as addressId6_1_, address0_1_.personId as personId7_1_, person1_.personId as personId3_0_ from ADDRESS address0_ left outer join PersonAddress address0_1_ on address0_.addressId=address0_1_.addressId left outer join PERSON person1_ on address0_1_.personId=person1_.personId where address0_.addressId=?
<br>Hibernate: select addresses0_.personId as personId3_2_, addresses0_.addressId as addressId2_, address1_.addressId as addressId6_0_, address1_1_.personId as personId7_0_, person2_.personId as personId3_1_ from PersonAddress addresses0_ inner join ADDRESS address1_ on addresses0_.addressId=address1_.addressId left outer join PersonAddress address1_1_ on address1_.addressId=address1_1_.addressId left outer join PERSON person2_ on address1_1_.personId=person2_.personId where addresses0_.personId=?
<b>Hibernate: insert into PersonAddress (personId, addressId) values (?, ?)
<br>Hibernate: insert into PersonAddress (personId, addressId) values (?, ?)</b>
<br>Dec 26, 2011 10:40:27 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
警告:SQL错误:1062 SQLSTATE:23000
2011年12月26日10点四十分27秒PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 错误:对于密钥1重复条目'1-3'
代码
@Entity<br>
@Table(name="PERSON")<br>
public class Person {<br>
@Id<br>
@GeneratedValue(strategy = GenerationType.AUTO)<br>
@Column(name = "personId")<br>
public int id;<br>
@OneToMany()<br>
@JoinTable(name = "PersonAddress",
joinColumns = {
@JoinColumn(name="personId", unique = true)},
inverseJoinColumns = {
@JoinColumn(name="addressId")})<br>
public Set<Address> addresses = new HashSet<Address>();<br>
}
@Entity
@Table(name = "ADDRESS")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "addressId")
public int id;
@ManyToOne(optional=true,cascade={CascadeType.ALL})
@JoinTable(name = "PersonAddress",
joinColumns = {@JoinColumn(name="addressId",insertable=false,updatable=true)},
inverseJoinColumns = {
@JoinColumn(name="personId")
})
public Person person;
}
这种关系的存在方式是一个人可以有多个地址,并且一个地址可以在没有人的情况下存在(地址可以是空的)。为了使用mappedBy =“person”属性,我必须在Address表中有parentId键。我不想要这个,因为地址只能属于一个人。连接表允许多个人与地址相关联。此外,这些字段为了简化而不公开,不准确。 – user1116536 2011-12-27 13:12:38
如果一个人有几个地址,并且一个地址可能属于多个人,那么您没有一对多关联,而是多对多关联。 Address实体应该有一个人员集合,而不是Person字段。无论您是否使用连接表,mappedBy都可以使用。它只是意味着:另一方有映射信息。但是,嘿,如果您不相信回答者(并且在hibernate标记中有538个选票,在JPA标记中有258个),为什么要问问题? – 2011-12-27 13:27:11