2016-03-04 96 views
2

這個例子來自JBOSS的hibernate教程。鏈接在那裏: http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#embeddables在Hibernate中添加約束教程

實施例79單向@OneToMany關聯

@Entity(name = "Person") 
public static class Person { 

    @Id 
    @GeneratedValue 
    private Long id; 
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) 
    private List<Phone> phones = new ArrayList<>(); 

    public Person() { 
    } 

    public List<Phone> getPhones() { 
     return phones; 
    } 
} 

@Entity(name = "Phone") 
public static class Phone { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String number; 

    public Phone() { 
    } 

    public Phone(String number) { 
     this.number = number; 
    } 

    public Long getId() { 
     return id; 
    } 

    public String getNumber() { 
     return number; 
    } 
} 
CREATE TABLE Person (
    id BIGINT NOT NULL , 
    PRIMARY KEY (id) 
) 

CREATE TABLE Person_Phone (
    Person_id BIGINT NOT NULL , 
    phones_id BIGINT NOT NULL 
) 

CREATE TABLE Phone (
    id BIGINT NOT NULL , 
    number VARCHAR(255) , 
    PRIMARY KEY (id) 
) 

ALTER TABLE Person_Phone 
ADD CONSTRAINT UK_9uhc5itwc9h5gcng944pcaslf 
UNIQUE (phones_id) 

ALTER TABLE Person_Phone 
ADD CONSTRAINT FKr38us2n8g5p9rj0b494sd3391 
FOREIGN KEY (phones_id) REFERENCES Phone 

ALTER TABLE Person_Phone 
ADD CONSTRAINT FK2ex4e4p7w1cj310kg2woisjl2 
FOREIGN KEY (Person_id) REFERENCES Person 

我的問題是,在這個例子中:

1)爲什麼添加約束看起來像一臺機器生成的字符串, 「FKr38us2n8g5p9rj0b494sd3391」?不應該使用更有意義的約束手動創建嗎?

2)在這種情況下ADD CONSTRAINT是否可選?

回答

1

爲什麼產生添加約束看起來像一臺機器串, 「FKr38us2n8g5p9rj0b494sd3391」?不應該用 更有意義的約束手動創建嗎?

當然,約束不是由數據庫生成的。它由Hibernate生成。

由於某些數據庫中的約束名稱長度限制,會生成這個奇怪的名稱FKr38us2n8g5p9rj0b494sd3391。例如,在Oracle數據庫中,長度不能超過30個符號。

Hibernate通過連接表和屬性名稱來生成約束名稱,並將結果轉換爲MD5,從而生成如FKr38us2n8g5p9rj0b494sd3391這樣的字符串。從休眠源

/** 
* Hash a constraint name using MD5. Convert the MD5 digest to base 35 
* (full alphanumeric), guaranteeing 
* that the length of the name will always be smaller than the 30 
* character identifier restriction enforced by a few dialects. 
* 
* @param s The name to be hashed. 
* 
* @return String The hashed name. 
*/ 
public String hashedName(String s) { 
    try { 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     md.reset(); 
     md.update(s.getBytes()); 
     byte[] digest = md.digest(); 
     BigInteger bigInt = new BigInteger(1, digest); 
     // By converting to base 35 (full alphanumeric), we guarantee 
     // that the length of the name will always be smaller than the 30 
     // character identifier restriction enforced by a few dialects. 
     return bigInt.toString(35); 
    } 
    catch (NoSuchAlgorithmException e) { 
     throw new HibernateException("Unable to generate a hashed name!", e); 
    } 
} 

這段代碼可以生成自己的約束名稱使用ImplicitNamingStrategy(唯一性和外鍵)。作爲一個例子,你可以參考Hibernate5NamingStrategy

還要指定約束名稱(通常情況下),您可以使用@ForeignKey@JoinColumn註釋。

對於連接表,您可以使用@JoinTable註釋,如@uditkhare建議的那樣。但是,你需要提供更多的信息(這是不是很方便)

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) 
@JoinTable(name="person_phones", 
    joinColumns = @JoinColumn(name = "f_person_pid", foreignKey = @ForeignKey(
      name = "fk_person_phones_person")), 
    inverseJoinColumns = @JoinColumn(name = "fk_phone", 
      foreignKey = @ForeignKey(name = "fk_person_phones_phone")), 
      uniqueConstraints = @UniqueConstraint(name = "uk_person_phones_phone", 
      columnNames = { "fk_phone" })) 
private List<Phone> phones = new ArrayList<>(); 

是添加約束在這種情況下,可選?

不是。它不是可選的。需要模擬@OneToMany關係。

+0

太好了。謝謝。 – user697911

+0

@ user697911不客氣。 –

0

是的,它只是由休眠產生的。

如果你想定義那些你自己,你可以使用如下的內容:

@OneToMany 
@JoinTable([email protected](name="my_unique_key", columnNames={"phones_id"})) 
+0

您的意思是3個'create table'語句是由開發人員製作的,但是「Alter table」是由DB添加的。因此,在本教程中,我只需要兩個類定義和表創建,而無需擔心「alter table」,如果我想試用教程。對? – user697911

+0

@ user697911所有模式創建腳本都是由Hibernate生成的,而不是由數據庫生成的。看到我的答案。 –

+0

@ v.ladynev是正確的,我編輯了我的答案 –