在Hibernate教程中添加CONSTRAINT

这个例子来自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 phones = new ArrayList(); public Person() { } public List 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)为什么ADD CONSTRAINT看起来像机器生成的字符串,“FKr38us2n8g5p9rj0b494sd3391”? 它不应该用更有意义的约束手动创建吗?

2)在这种情况下,ADD CONSTRAINT是否可选?

为什么ADD CONSTRAINT看起来像机器生成的字符串,“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 phones = new ArrayList<>(); 

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

不,它不是可选的。 需要建模@OneToMany关系。

是的,仅由hibernate生成。

如果您想自己定义,可以使用以下内容:

 @OneToMany @JoinTable(uniqueConstraints=@UniqueConstraint(name="my_unique_key", columnNames={"phones_id"}))