英文:
Migrating from Hibernate 3.6 to 4.2: Hibernate auto generates foreign keys
问题
以下是翻译好的内容:
问题
升级后,Hibernate开始自动生成一个指向相同表的外键。现在,在尝试持久化新客户时,会抛出ConstraintViolationException
。
细节
这里有我所说的一个图片:
这是相应类的代码:
@Entity
@Table(name = "customers")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Customer extends AbstractModel {
public Customer(final Provider provider) {
this.provider = provider;
}
@Required
@ManyToOne(cascade = CascadeType.REFRESH)
public Provider provider;
@MaxSize(1023)
public String note;
public String getNote() { return note; }
...
}
如您所见,它继承自AbstractModel
,这是一个@MappedSuperclass
,包含用于我们所有模型类的主键的id
属性。它是一个@GeneratedValue
。
它本身是一个超类。我不知道它是否重要,所以我只会包括一个其子类的代码和架构:
以及相应的代码:
@Entity
@Table(name="unregistered_customers")
public class UnregisteredCustomer extends Customer {
@MaxSize(MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
@Column(nullable = false, length = MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
public String userName;
@Email
@MaxSize(MAX_SIZE_OF_EMAIL_ADDRESSES)
@Column(unique = false, length = MAX_SIZE_OF_EMAIL_ADDRESSES)
public String email;
@MaxSize(MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
@Column(length = MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
public String mobile;
public UnregisteredCustomer(final Provider provider) {
super(provider);
}
}
研究
我已经查阅了迁移指南,但其中没有与我的问题相关的内容。我还查看了Hibernate文档,特别是与@Inheritance
相关的部分。不幸的是,我没有找到任何关于自动生成外键的信息。
问题
如何阻止Hibernate添加这个自引用外键?
编辑 1
根据您的请求,这是超类的代码:
@MappedSuperclass
public abstract class AbstractModel extends AbstractBaseModel {
@Id
@GeneratedValue
public Long id;
public Long getId() {
return id;
}
@Override
public Object _key() {
return id;
}
}
还有超类的超类的代码:
@MappedSuperclass
public abstract class AbstractBaseModel extends GenericModel {
public static final int MAX_SIZE_OF_NAMES_AND_IDENTIFIERS = 80;
public static final int MAX_SIZE_OF_COMMENTS_AND_DESCRIPTIONS = 5000;
public static final int MAX_LIST_SIZE = 30;
public static final int MAX_SIZE_OF_EMAIL_ADDRESSES = 255;
public static final int MAX_SIZE_OF_JSON_CONTENT_FIELDS = 65535;
@Column(nullable = false, unique = true)
public String uuid;
@Column(nullable = false)
public Long created;
public DateTime getCreatedAsDate() {
return DateUtil.dateTimeWithSystemTimezone(created);
}
@Column(nullable = false)
public Long lastModified;
@PrePersist
protected void prePersist() {
final Long nowInMillis = DateUtil.dateTimeWithSystemTimezone().getMillis();
if (uuid == null) {
uuid = UuidUtil.newUUIDAsString();
Logger.trace("为实体创建了新的Uuid:%s", uuid);
}
if (created == null) {
created = nowInMillis;
}
if (lastModified == null) {
lastModified = nowInMillis;
}
}
@PreUpdate
protected void preUpdate() {
lastModified = DateUtil.dateTimeWithSystemTimezone().getMillis();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
final AbstractBaseModel other = (AbstractBaseModel) obj;
return new EqualsBuilder().append(uuid, other.uuid).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(uuid).toHashCode();
}
}
希望这些信息对您有所帮助。如果您需要进一步的帮助,请随时告诉我。
英文:
As the title suggests: I am currently migrating from Hibernate 3.6 to 4.2.
PROBLEM
After the upgrade, Hibernate started to automatically generate a foreign key that points to the same table. Now, when trying to persist a new customer, a ConstraintViolationException
is thrown.
DETAILS
Here's a picture of what I mean:
Here is the code of the corresponding class:
@Entity
@Table(name = "customers")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Customer extends AbstractModel {
public Customer(final Provider provider) {
this.provider = provider;
}
@Required
@ManyToOne(cascade = CascadeType.REFRESH)
public Provider provider;
@MaxSize(1023)
public String note;
public String getNote() { return note; }
...
}
As you can see, it extends from AbstractModel
which is a @MappedSuperclass
and contains the id
property which serves as a primary key for all of our model classes. It's a @GeneratedValue
.
It's a superclass itself. I don't know whether it's important so I am just going to include the code and schema of one of its child classes:
And the corresponding code:
@Entity
@Table(name="unregistered_customers")
public class UnregisteredCustomer extends Customer {
@MaxSize(MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
@Column(nullable = false, length = MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
public String userName;
@Email
@MaxSize(MAX_SIZE_OF_EMAIL_ADDRESSES)
@Column(unique = false, length = MAX_SIZE_OF_EMAIL_ADDRESSES)
public String email;
@MaxSize(MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
@Column(length = MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
public String mobile;
public UnregisteredCustomer(final Provider provider) {
super(provider);
}
RESEARCH
I already looked into the migration guide but nothing in there seems to be related to my issue.
I also looked into the Hibernate documentation especially into the section dealing with @Inheritance
. Sadly, I didn't find anything concerning auto generated foreign keys.
QUESTION
How do I stop Hibernate from adding this self-referencing foreign key?
EDIT 1
As requested, the super class:
@MappedSuperclass
public abstract class AbstractModel extends AbstractBaseModel {
@Id
@GeneratedValue
public Long id;
public Long getId() {
return id;
}
@Override
public Object _key() {
return id;
}
}
Also, the super class of the super class:
@MappedSuperclass
public abstract class AbstractBaseModel extends GenericModel {
public static final int MAX_SIZE_OF_NAMES_AND_IDENTIFIERS = 80;
public static final int MAX_SIZE_OF_COMMENTS_AND_DESCRIPTIONS = 5000;
public static final int MAX_LIST_SIZE = 30;
public static final int MAX_SIZE_OF_EMAIL_ADDRESSES = 255;
public static final int MAX_SIZE_OF_JSON_CONTENT_FIELDS = 65535;
@Column(nullable = false, unique = true)
public String uuid;
@Column(nullable = false)
public Long created;
public DateTime getCreatedAsDate() {
return DateUtil.dateTimeWithSystemTimezone(created);
}
@Column(nullable = false)
public Long lastModified;
@PrePersist
protected void prePersist() {
final Long nowInMillis = DateUtil.dateTimeWithSystemTimezone().getMillis();
if (uuid == null) {
uuid = UuidUtil.newUUIDAsString();
Logger.trace("Created new Uuid for entity: %s", uuid);
}
if (created == null) {
created = nowInMillis;
}
if (lastModified == null) {
lastModified = nowInMillis;
}
}
@PreUpdate
protected void preUpdate() {
lastModified = DateUtil.dateTimeWithSystemTimezone().getMillis();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
final AbstractBaseModel other = (AbstractBaseModel) obj;
return new EqualsBuilder().append(uuid, other.uuid).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(uuid).toHashCode();
}
}
答案1
得分: 2
Put @Inheritance(strategy = InheritanceType.JOINED) to the parent entity (AbstractModel) not to the child. And customize the foreign key constraint using @PrimaryKeyJoinColumn at your child entity. Check out Part 4 (Joined Table) at https://www.baeldung.com/hibernate-inheritance to see it more clearly!
英文:
Put @Inheritance(strategy = InheritanceType.JOINED) to the parent entity (AbstractModel) not to the child. And customize the foreign key constraint using @PrimaryKeyJoinColumn at your child entity. Check out Part 4 (Joined Table) at https://www.baeldung.com/hibernate-inheritance to see it more clearly!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论