![](/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.