我是JPA&我正在学习“Java Persistence With Hibernate 2nd Edition”一书。 @JoinTable在@OneToMany双向List(带@OrderColumn)映射方面遇到了一些困难。我没有遇到@JoinColumn的任何问题,但似乎我在@JoinTable的情况下做错了。我在下面给出了我的例子。
ADDRESS CLASS:
@Entity
@Table(name = "ADDRESS")
public class Address {
@Id
@GeneratedValue(generator = "MY_ID_GENERATOR")
@Column(name="_ADDRESS_ID")
private Long addressId;
@NotNull
@Column(name="_CITY", nullable = false)
protected String city;
//-------------------------------------
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(
name = "ADDRESS_LIST",
joinColumns = {@JoinColumn(name = "_A_ID", unique = true, updatable = false, insertable = false, referencedColumnName = "_ADDRESS_ID")},
inverseJoinColumns = {@JoinColumn(name = "_P_ID", updatable = false, insertable = false, referencedColumnName = "_PERSON_ID")}
)
private Person person;
//-------------------------------------
protected Address() {}
public Address(@NotNull String city) {
super();
this.city = city;
}
public Address(@NotNull String city, Person person) {
super();
this.city = city;
this.person = person;
}
public Long getId() { return addressId; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public Person getPerson() { return person; }
public void setPerson(Person person) { this.person = person; }
}
PERSON CLASS:
@Entity
@Table(name = "PERSON")
public class Person {
@Id
@GeneratedValue(generator = "MY_ID_GENERATOR")
@Column(name="_PERSON_ID")
private Long personId;
@NotNull
@Column(name="_NAME", nullable = false, length = 50)
private String name;
//-------------------------------------
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, orphanRemoval = true)
@JoinTable(
name = "ADDRESS_LIST",
joinColumns = {@JoinColumn(name = "_P_ID", referencedColumnName = "_PERSON_ID")},
inverseJoinColumns = {@JoinColumn(name = "_A_ID", unique = true, referencedColumnName = "_ADDRESS_ID")}
)
@OrderColumn(name = "_ORDER", nullable = false)
private List<Address> addressList = new ArrayList<>();
//-------------------------------------
public Person() {
super();
}
public Person(@NotNull String name) {
super();
this.name = name;
}
public Long getPersonId() { return personId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<Address> getAddressList() { return addressList; }
public void setAddressList(List<Address> addressList) { this.addressList = addressList; }
}
现在在主要课程中,如果我照顾双方协会,那就不起作用!!
Person person = new Person("Sourangshu Biswas");
person.getAddressList().add(new Address("Siliguri", person));
person.getAddressList().add(new Address("Kolkata", person));
person.getAddressList().add(new Address("Chennai", person));
给出错误!!
Caused by: java.sql.SQLException: Field '_P_ID' doesn't have a default value.
但如果我没有在“地址()”缩写器中传递“person”对象,它就可以了。
Person person = new Person("Sourangshu Biswas");
person.getAddressList().add(new Address("Siliguri"));
person.getAddressList().add(new Address("Kolkata"));
person.getAddressList().add(new Address("Chennai"));
我已经检查了数据库,我在“_ORDER”列中也获得了值!但问题是这是如何工作的!据我所知,我们必须在双向关联中照顾双方。当我在“地址()”缩写器中传递“人物”对象时为什么它不起作用!!!! ?? “人”对象尚未持久,这是为什么?但是我在映射的其他类型(SET / BAG)中完成了同样的事情,那时它起作用了。
答案 0 :(得分:0)
注意:它是双向LIST映射,我也想使用OrderColumn。根据&#34; Java Persistence With Hibernate第2版&#34;本书(第185页),这个例子是一个例外。
本书提到的是使用连接列创建有序双向一对多关联的解决方法,这是非常不同的。实际上,您在这里创建了两个碰巧使用相同连接表的单独关联。现在:
如果我没有通过&#34;那个人&#34; &#34;地址()&#34;中的对象缩窄,它正在发挥作用。
当Address.person
设置为null
时,Hibernate不会尝试保持多对一关联。因此,生成单个INSERT
语句(仅存储一对多关联):
INSERT INTO ADDRESS_LIST(_P_ID, _A_ID) VALUES (?, ?);
在主要课程中,如果我照顾双方协会,它就不起作用!!
如果您将Address
添加到Person.addressList
并将非空Person
分配给Address.person
,Hibernate会尝试将两个关联都保留。将生成两个INSERT
语句:一个用于一对多关联(类似于上面的一个),另一个用于多对一关联 - 如下所示:
INSERT INTO ADDRESS_LIST() VALUES ();
为什么空列列表和空值列表? 因为您已标记了联接表insertable=false
的两个加入列。数据库抱怨缺少_P_ID
列的值 - 这是可以理解的,因为_P_ID
不能是NULL
,并且没有默认值可供使用。
当然,如果删除insertable=false
,则两个INSERT
语句将完全相同,从而导致约束违规或ADDRESS_LIST
中的重复行。
长话短说:你不应该照顾协会的双方,因为这不是双向关联 - 这实际上是两个完全独立的关联。
请注意,对于类似于加入列方法的解决方法,您需要将整个多对一@JoinTable
标记为insertable=false
,而不仅仅是单个连接列 - JPA不支持的内容。