英文:
Why hibernate generates unnecessary constraint?
问题
以下是翻译好的内容:
我在使用Hibernate中的双向关系生成的SQL方面遇到了一个奇怪的问题。以下是代码示例。
首先是@OneToMany
关系:
@Entity
@Table(name = "employers")
public class Employer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "eid")
private Long employerId;
private String name;
@OneToMany(mappedBy = "titleId")
private Set<Title> titles = new TreeSet<>();
// 获取器/设置器...
}
然后是@ManyToOne
关系:
@Entity
@Table(name = "titles")
public class Title {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "tid")
private long titleId;
/**
* 不确定是否需要在这里建立双向关系。
*/
@ManyToOne
@JoinColumn(name = "employerId")
private Employer employer;
// 获取器/设置器...
}
我对Spring Boot和Hibernate相对较新,所以这是我尝试运行的第一件事情。根据我参考的教程和文档,在我的情况下生成的SQL是错误的。
以下是生成的SQL(Postgres9Dialect
)
CREATE TABLE public.items
(
item_id bigint NOT NULL DEFAULT nextval('items_item_id_seq'::regclass),
text character varying(255) COLLATE pg_catalog."default",
title_tid bigint,
CONSTRAINT items_pkey PRIMARY KEY (item_id),
CONSTRAINT fkkwhqrl3vscoqcacws6kgsdlx5 FOREIGN KEY (item_id)
REFERENCES public.titles (tid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
CONSTRAINT fkluhgxmnakeuroph186b2k05eq FOREIGN KEY (title_tid)
REFERENCES public.titles (tid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
问题出在这个约束上:
CONSTRAINT fkkwhqrl3vscoqcacws6kgsdlx5 FOREIGN KEY (item_id)
REFERENCES public.titles (tid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
这会导致如果标题ID(tid
)超过雇主ID(雇主表中的eid
)的最高编号,将不允许创建其他标题。生成的雇主表是正确的。
如果我手动删除这个约束,那么它就会按预期工作。
为什么会创建这个错误的约束?我漏掉了什么?
(另外,这里的"title"是指一个人在特定雇主那里拥有的头衔,而不是书的标题,因此我不是在尝试结合雇主和作者教程)
英文:
I'm having a strange problem with the SQL generated by a bidirectional relationship in Hibernate. Here's the code.
First the @OneToMany
side:
@Entity
@Table(name = "employers")
public class Employer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "eid")
private Long employerId;
private String name;
@OneToMany(mappedBy = "titleId")
private Set<Title> titles = new TreeSet<>();
// Getters/setters...
}
And the @ManyToOne
side:
@Entity
@Table(name = "titles")
public class Title {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "tid")
private long titleId;
/**
* Not sure if I need a bi-directional relation here.
*/
@ManyToOne
@JoinColumn(name = "employerId")
private Employer employer;
// Getters/setters...
}
I'm fairly new to springboot and hibernate, so this is the first thing I've attempted that would actually run. Based on the tutorials and the documentation I've referenced, the SQL generated in my case is wrong.
Here's the generated SQL (Postgres9Dialect
)
CREATE TABLE public.items
(
item_id bigint NOT NULL DEFAULT nextval('items_item_id_seq'::regclass),
text character varying(255) COLLATE pg_catalog."default",
title_tid bigint,
CONSTRAINT items_pkey PRIMARY KEY (item_id),
CONSTRAINT fkkwhqrl3vscoqcacws6kgsdlx5 FOREIGN KEY (item_id)
REFERENCES public.titles (tid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
CONSTRAINT fkluhgxmnakeuroph186b2k05eq FOREIGN KEY (title_tid)
REFERENCES public.titles (tid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
The problem is this constraint:
CONSTRAINT fkkwhqrl3vscoqcacws6kgsdlx5 FOREIGN KEY (item_id)
REFERENCES public.titles (tid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
It has the effect of not allowing additional titles from being created if the title id (tid
) exceeds the highest number of employer ids (eid in the employer table). The generated employers table is correct.
If I delete this constraint manually, then it works as expected.
Why is it creating this erroneous constraint? What am I missing?
(as an aside, title refers to a title one would have for a particular employer, not a book title, so I am not trying to combine employer & author tutorials)
答案1
得分: 5
你应该以以下方式更正你的映射:
@Entity
@Table(name = "employers")
public class Employer {
@OneToMany(mappedBy = "employer")
private Set<Title> titles = new TreeSet<>();
// ...
}
@Entity
@Table(name = "titles")
public class Title {
@ManyToOne
@JoinColumn(name = "employerId")
private Employer employer;
// ...
}
mappedBy
应该保存关联的另一侧的字段名。
英文:
You should correct your mapping in this way:
@Entity
@Table(name = "employers")
public class Employer {
@OneToMany(mappedBy = "employer")
private Set<Title> titles = new TreeSet<>();
// ...
}
@Entity
@Table(name = "titles")
public class Title {
@ManyToOne
@JoinColumn(name = "employerId")
private Employer employer;
// ...
}
The mappedBy
should hold the field name of another side of association.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论