一尘不染

在Hibernate教程中添加CONSTRAINT

hibernate

此示例来自JBOSS的hibernate教程。该链接位于:http
:
//docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#embeddables。

例子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是可选的吗?


阅读 338

收藏
2020-06-20

共1个答案

一尘不染

为什么添加约束看起来像机器生成的字符串“ FKr38us2n8g5p9rj0b494sd3391”?难道不是应该在一个更有意义的约束下手动创建它吗?

当然,约束不是由数据库生成的。它是由Hibernate生成的。

FKr38us2n8g5p9rj0b494sd3391由于某些数据库中的约束名称长度受到限制,因此生成了这个奇怪的名称。例如,在Oracle数据库中,其长度不能超过30个符号。

Hibernate通过连接表和属性名称来生成约束名称,并将结果转换为MD5,生成类似的字符串FKr38us2n8g5p9rj0b494sd3391。该代码段来自Hibernate源代码

/**
 * 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<>();

在这种情况下,ADD CONSTRAINT是可选的吗?

否。这不是可选的。需要建立@OneToMany关系模型。

2020-06-20