簡體   English   中英

JPA 2.0(Hibernate)使用@JoinTable為@OneToMany生成了不正確的聯接表PK

[英]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_idaddress_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM