Hibernate创建冗余的多对多表 [英] Hibernate creating redundant many-to-many tables
问题描述
在开发我的Spring Boot应用程序时,我不得不放弃数据库,让Hibernate再次使用 hibernate.hbm2ddl.auto = update
生成它。之后,我想确保它做了我想做的所有事情,所以我打电话给MySQL Workbench对我的整个数据库进行逆向工程。当我这样做时,我注意到由于某种原因,我的模式中有两倍的表。我的表中有很多实体关系,但它们都是一对多的,但由于某种原因,几乎所有的一对多关系都是由Hibernate生成的多对多连接表组成的。这对我来说是一个惊喜,因为这在以前没有发生在同一个Web应用程序中。
这里有一个双向关联,双方都是所有者,基本上将其转变为两个独立的协会。在一对多关联中,所有者通常是多对一的(注意 mappedBy
属性):
OneToMany(fetch = FetchType.EAGER,targetEntity = Skill.class,mappedBy =parent)
@Cascade({CascadeType.DETACH})
private Set< ;技能>儿童;
通过这种方式,Hibernate在维护关系时将忽略一端(并且不会创建连接表这是 @OneToMany
没有 @JoinColumn
的关联的默认配置。)
While developing my Spring Boot application I had to drop my database and have Hibernate generate it again with hibernate.hbm2ddl.auto=update
. After that I wanted to make sure it did everything like I wanted to so I called MySQL Workbench to reverse engineer my entire database. When I did that, I noticed that for some reason there were twice as many tables in my schema. I have a lot of entity relationships in my table, but all of them are one-to-many, yet for some reason for almost all of my one-to-many relationships Hibernate has generated many-to-many join tables. It came as a surprise to me because this didn't happen before with the same web application.
My search through SO has only led me to this question which seems irrelevant.
Now I will provide samples, but I have a lots of code and I want to keep it short, so I will cut to only one example. If you need to see more, please specify this in your answer.
So, for instance, I have this entity:
@SuppressWarnings("serial")
@Entity
@Indexed
@Table(name = "SKILL")
public class Skill extends AbstractDomainObject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", nullable = false)
private long id;
//Some properties
@ManyToOne(fetch = FetchType.EAGER, targetEntity = Skill.class)
@JoinColumn(name = "PARENT", nullable = true)
@Cascade({CascadeType.DETACH})
//Cascade annotations are from Hibernate, all else except for
//"Indexed" are from javax.persistence
private Skill parent;
@OneToMany(fetch = FetchType.EAGER, targetEntity = Skill.class)
@Cascade({CascadeType.DETACH})
private Set<Skill> children;
//Getters, setters, etc
}
You can see that this entity references itself. Skills are a tree here. So, Hibernate interprets this as:
In fact, skill_skill
table isn't even being used. You can see that skill
still references itself without this table. When I insert new data in this table, nothing new appears in skill_skill
. Although these two entities for some reason don't get extra table:
These two object have one-side relationship here:
@SuppressWarnings("serial")
@Entity
@Table(name = "ROLE")
public class Role implements DomainObject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", nullable = false)
private long id;
@Column(name = "ROLENAME", nullable = false, length = 50)
private String rolename;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "OWNER", nullable = false)
private User owner;
}
Some causes I can think on:
- Abstract
AbstractDomainObject
superclass. It only has protected boilerplate functions. It didn't cause any problem before though. @Cascade({CascadeType.DETACH})
annotation that I added. Although seems unlikely.- My last change was that I created a second data source in my project, this is why I changed my
@EnableAutoConfiguration
to@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
. Could it be that Hibernate behaves somehow differently now? - I also moved all my entities causing trouble to a different package.
What you have here is a bidirectional association in which both sides are owners, turning it basically to two independent associations. In a one-to-many association the owner is usually the many-to side (note the mappedBy
attribute):
OneToMany(fetch = FetchType.EAGER, targetEntity = Skill.class, mappedBy = "parent")
@Cascade({CascadeType.DETACH})
private Set<Skill> children;
This way Hibernate will ignore one-to side when maintaining the relationship (and will not create the join table which is the default configuration for @OneToMany
association without @JoinColumn
).
这篇关于Hibernate创建冗余的多对多表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!