我确定之前已经问过这个问题,但我似乎找不到答案.我正在使用Hibernate 4.0来建立基本关系.我有一个可以包含地址的Person对象(是的,从另一个站点获得代码认为它可以工作,但事实并非如此).我想使用连接表.我觉得我已经尝试了所有可能的组合,但不断提出相同的错误:"重复输入'1-3'为键1".基本上是在我设置双方关系(Person/Address)之后尝试提交事务时发生的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>
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
警告:SQL错误:1062,SQLState:23000
Dec 26,2011 10:40: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;
}
Run Code Online (Sandbox Code Playgroud)
发展的关键原则之一是DRY:不要重复自己.JPA应用它,因此当您具有双向关联时,您应该在关联的一侧声明此关联的映射仅一次.另一方应该说:我使用mappedBy属性映射为另一方声明的.
由于您将双向关联映射了两次,因此Hibernate认为您有两个不同的关联,因此会进行两次插入.
这是如何声明地址集:
@OneToMany(mappedBy = "person")
private Set<Address> addresses = new HashSet<Address>();
Run Code Online (Sandbox Code Playgroud)
其他评论:
| 归档时间: |
|
| 查看次数: |
5813 次 |
| 最近记录: |