![](/img/trans.png)
[英]JPA 2.0 Hibernate @OneToMany + @MapKeyJoinColumn
[英]JPA 2.0 (Hibernate) generates incorrect join table PK for @OneToMany with @JoinTable
我在Hibernate 4.3.5中使用了JPA 2.0,並試圖使用Hibernate自動生成我的表。
我在聯系人實體中創建了以下條目:
/**
* Address
*/
@Valid
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "contact_address", joinColumns = @JoinColumn(name = "contact_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "address_id", referencedColumnName = "id"))
@OrderColumn
private List<Address> addresses;
Hibernate可以正確創建聯系人表,但是創建聯接表時沒有正確的PK:
CREATE TABLE `contact_address` (
`contact_id` bigint(20) NOT NULL,
`address_id` bigint(20) NOT NULL,
`addresses_order` int(11) NOT NULL,
PRIMARY KEY (`contact_id`),
UNIQUE KEY `UK_mvvtppjfu6d0lcjm83u5youn8` (`address_id`),
CONSTRAINT `FK_4fntyt0q2l6vkfg7t38pg4i94` FOREIGN KEY (`contact_id`) REFERENCES `contact` (`id`),
CONSTRAINT `FK_mvvtppjfu6d0lcjm83u5youn8` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
此處列出的PK只是contact_id
,這是不正確的。 那將不允許我分配多個地址。 而是,PK應該是contact_id
和address_id
的復合PK。
Hibernate是否有故障,或者我的JPA批注中有問題? 這是一種單向關聯。
正如一些人指出的那樣,從技術上來說,我不需要@OneToMany的聯接表,但是鑒於我需要在其他實體對象中使用Address實體,因此對於所有對象使用聯接表對我來說更干凈協會。
我已經設法使用@ManyToMany關聯並在連接列上指定了唯一約束來解決一個問題,但是我試圖了解我的JPA是否有問題或它是否是Hibernate錯誤。
如果您需要“聯系人”和“地址”之間的一對多關系,其中一個聯系人有多個地址。 沒有關聯表就可以滿足以下條件。
@Valid
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name="contact_id", referencedColumnName="id")
private List<Address> addresses;
您需要為問題添加更多詳細信息。 例如,您如何注釋Address
實體?
無論如何,如果您正確注釋和定義了實體,則Hibernate將為您正確生成表:
@Entity
public class Contact {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator"
)
private String id;
private String fullName;
@OneToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "contact_addresses",
joinColumns = @JoinColumn(
name = "contact_id",
referencedColumnName = "id"
),
inverseJoinColumns = @JoinColumn(
name = "address_id",
referencedColumnName = "id"
)
)
private Set<Address> addresses = new HashSet<>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFullName() {
return fullName;
}
public void setFullName(String brand) {
this.fullName = brand;
}
public Set<Address> getAddresses() {
return addresses;
}
public void setAddresses(Set<Address> contacts) {
this.addresses = addresses;
}
public void addAddress(Address address) {
getAddresses().add(address);
address.setContact(this);
}
}
@Entity
public class Address {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator"
)
private String id;
private String streetAddress;
@ManyToOne(cascade = CascadeType.ALL)
private Contact contact;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getStreetAddress() {
return streetAddress;
}
public void setStreetAddress(String name) {
this.streetAddress = name;
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
}
這是一個示例測試用例:
@Test
public void testContactAddresses() {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("ContactAddresses");
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Contact contact = new Contact();
contact.setFullName("Steve Ballmer");
Address address1 = new Address();
address1.setStreetAddress("Developers Street");
Address address2 = new Address();
address2.setStreetAddress("Developers Developers Street");
Address address3 = new Address();
address3.setStreetAddress("Developers Developers Developers Street");
contact.addAddress(address1);
contact.addAddress(address2);
contact.addAddress(address3);
entityManager.persist(contact);
transaction.commit();
}
這是Hibernate執行的DDL語句:
Hibernate: drop table Address if exists
Hibernate: drop table Contact if exists
Hibernate: drop table contact_addresses if exists
Hibernate: create table Address (id varchar(255) not null, streetAddress varchar(255), contact_id varchar(255), primary key (id))
Hibernate: create table Contact (id varchar(255) not null, fullName varchar(255), primary key (id))
Hibernate: create table contact_addresses (
contact_id varchar(255) not null,
address_id varchar(255) not null,
primary key (contact_id, address_id)
)
Hibernate: alter table contact_addresses add constraint UK_mxmb2y0iu8624h4rrdamayobp unique (address_id)
Hibernate: alter table Address add constraint FK98iji1i9ycae5a36rman0vd17 foreign key (contact_id) references Contact
Hibernate: alter table contact_addresses add constraint FK6n27pwv86i3cx03jv3i9taidw foreign key (address_id) references Address
Hibernate: alter table contact_addresses add constraint FKmw2sdpyxrxj3obg1x1ltdlwbo foreign key (contact_id) references Contact
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.