JPA之实体之间一对多关系(二)
JPA在生成数据表的时候,实体与实体之间主要有三种关系,分别是:一对一
,一对多
,多对多
三种关系,其中一对多
最简单,多对多
最复杂,下面我们就分别对三种关系进行演示。
实体与实体之间一对多关系配置
有两张表,分别是banner
和banner_item
,两者之间的关系是一对多,那么我们要生成数据库表怎么生成呢?
- Banner.java
@Entity
//@Table(name = "banner")
public class Banner {
@Id
private long id;
@Column(length = 20)
private String name;
private String description;
@Transient // 该注解表示不生成该字段到数据库
private String img;
@Column(length = 12)
private String title;
@OneToMany
private List<BannerItem> items;
}
- BannerItem.java
@Entity
public class BannerItem {
@Id
private long id;
private String img;
private String keyword;
private short type;
private String name;
}
由于Banner
可以有多个BannerItem
,因此在Banner
实体中,有一个private List<BannerItem> items
的属性,来标明对应有多个的 BannerItem
,当运行程序后,那么会在数据库中生成三张表,分别是:banner
、banner_item
、banner_items
,而banner_items
是两者的中间表,也就是关系表。
那么这里有一个问题,正常情况下,只有是多对多的关系,才会生成中间关系表,这里为什么会生成呢?因为在banner_item中是必须要指明属于那个banner,但是这里并没有指明外键关系,所以JPA也不知道两个表之间的关系,因此就只好生成了一个中间表,在第三种表进行维护两者之间的关系。
注意,在Banner中我们已经维护有一个List
如何指定外键呢?
- 在 BannerItem 中添加
private long bannerId
- 在 Banner 中添加
@JoinColumn(name = "bannerId")
代码修改如下:
- Banner
@Entity
//@Table(name = "banner")
public class Banner {
@Id
private long id;
@Column(length = 20)
private String name;
private String description;
@Transient // 该注解表示不生成该字段到数据库
private String img;
@Column(length = 12)
private String title;
@OneToMany
@JoinColumn(name = "bannerId")
private List<BannerItem> items;
}
- BannerItem
@Entity
public class BannerItem {
@Id
private long id;
private String img;
private String keyword;
private short type;
private String name;
// 用于标明和Banner之间的关系
private long bannerId;
}
再生成数据库表后,在banner_item
中就会有一个 banner_id
的外键字段
说明
如果已经生成有 banner_items
的话,再执行该表是不会删除的,需要自己手工删除,或者去修改配置文件中的ddl-auto: update
为 create-drop
引申的问题
上面的方式中,我们使用了物理外键,那么到底用不用物理外键呢?使用物理外键的好处就是能保证数据的强一致性,缺点就是太过于繁琐。在目前技术发展情况下,我个人是不建议是用物理外键的。那么不用物理外键的话,如何保证数据的一致性呢?最好的办法就是在代码中,去做比较强的数据校验,去保证数据的一致性。