在开发 Spring Boot 应用程序时,我必须删除数据库并让 Hibernate 再次生成它hibernate.hbm2ddl.auto=update
。之后,我想确保它按照我想要的方式执行所有操作,因此我调用 MySQL Workbench 对我的整个数据库进行逆向工程。当我这样做时,我注意到由于某种原因,我的架构中的表数量是原来的两倍。我的表中有很多实体关系,但它们都是一对多的,但出于某种原因,对于几乎所有的一对多关系,Hibernate 都生成了多对多连接表。这让我感到惊讶,因为以前在同一个 Web 应用程序中没有发生过这种情况。
我对 SO 的搜索只会让我找到this似乎无关紧要的问题。
现在我将提供示例,但我有很多代码,我想保持简短,所以我将只讲一个示例。如果您需要查看更多信息,请在您的答案中注明。
例如,我有这个实体:
@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
}
您可以看到该实体引用了自身。技能在这里是一棵树。因此,Hibernate 将其解释为:
技能_技能图像
实际上,skill_skill
表甚至没有被使用。你可以看到skill
没有这个表仍然引用自身。当我在此表中插入新数据时,没有任何新内容出现skill_skill
。尽管这两个实体由于某种原因没有获得额外的表:
角色和用户形象
这两个对象在这里具有单边关系:
@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;
}
我可以思考的一些原因:
- 抽象的
AbstractDomainObject
超类。它仅具有受保护的样板函数。不过之前并没有造成任何问题。
-
@Cascade({CascadeType.DETACH})
我添加的注释。虽然看起来不太可能。
- 我的最后一个更改是我在项目中创建了第二个数据源,这就是我更改我的
@EnableAutoConfiguration
to @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
。难道 Hibernate 现在的行为有所不同吗?
- 我还将所有造成麻烦的实体移至不同的包。