Spring Data JPA 多表
表的关系
-
一对一
-
一对多,多对一
一(主表),多(从表)。在多的表中加一个数据项用于存储主表中的主键
-
多对多
利用中间表
Spring Data JPA多表,实体类关系构建
1.确定表关系
2.编写实体类
3.配置映射关系
eg:客户类(一)----------联系人类(多)
客户类(Customer)
package cn.itcast.domain;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
/**
* 1.实体类和表的映射关系
* @Eitity
* @Table
* 2.类中属性和表中字段的映射关系
* @Id
* @GeneratedValue
* @Column
*/
@Entity
@Table(name="cst_customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="cust_id")
private Long custId;
@Column(name="cust_address")
private String custAddress;
@Column(name="cust_industry")
private String custIndustry;
@Column(name="cust_level")
private String custLevel;
@Column(name="cust_name")
private String custName;
@Column(name="cust_phone")
private String custPhone;
@Column(name="cust_source")
private String custSource;
//配置客户和联系人之间的关系(一对多关系)
/**
* 使用注解的形式配置多表关系
* 1.声明关系
* @OneToMany : 配置一对多关系
* targetEntity :对方对象的字节码对象
* 2.配置外键(中间表)
* @JoinColumn : 配置外键
* name:外键字段名称
* referencedColumnName:参照的主表的主键字段名称
*
* * 在客户实体类上(一的一方)添加了外键了配置,所以对于客户而言,也具备了维护外键的作用
*
*/
// @OneToMany(targetEntity = LinkMan.class)
// @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
/**
* 放弃外键维护权
* mappedBy:对方配置关系的属性名称\
* cascade : 配置级联(可以配置到设置多表的映射关系的注解上)
* CascadeType.all : 所有
* MERGE :更新
* PERSIST :保存
* REMOVE :删除
*
* fetch : 配置关联对象的加载方式
* EAGER :立即加载
* LAZY :延迟加载
*/
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
private Set<LinkMan> linkMans = new HashSet<>();
set/get
}
在配置实体类(一的一方)时应该注意到的
放弃外键维护权
添加
注意
放弃外键维护权的好处,放弃外键维护权或怎么用都行
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testAdd() {
//创建一个客户,创建一个联系人
Customer customer = new Customer();
customer.setCustName("百度");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李");
/**
* 配置了客户到联系人的关系
* 从客户的角度上:发送两条insert语句,发送一条更新语句更新数据库(更新外键)
* 由于我们配置了客户到联系人的关系:客户可以对外键进行维护
*/
customer.getLinkMans().add(linkMan);
customerDao.save(customer);
linkManDao.save(linkMan);
}
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testAdd1() {
//创建一个客户,创建一个联系人
Customer customer = new Customer();
customer.setCustName("百度");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李");
/**
* 配置联系人到客户的关系(多对一)
* 只发送了两条insert语句
* 由于配置了联系人到客户的映射关系(多对一)
*
*
*/
linkMan.setCustomer(customer);
customerDao.save(customer);
linkManDao.save(linkMan);
}
删除
正常写法
@OneToMany(targetEntity = LinkMan.class)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
放弃外键维护权的写法
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
//cascabe联级删除
在不放弃外键维护权时,我们想要删除主表中的数据的话,数据库就会不让我们删除,因为从表中的外键占用了主表的主键所以不能删除。
我们正常的的逻辑就是当我们想要删除主表中的数据时,应该连同从表中有关数据一同删除。
那么想要实现上述逻辑就应进行如下配置:
1.放弃外键的维护权
是为了能不删除从表中的相关数据而直接删除主表中的数据
2.联级删除
是为了直接删除主表中的数据后自动删除从表中的数据
其实这么配置就是为了更符合我们的逻辑,方便写代码,不这样配置也可以就是在删除的时候会麻烦一些。
联系人类(LinkMan)
package cn.itcast.domain;
import javax.persistence.*;
@Entity
@Table(name = "cst_linkman")
public class LinkMan {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "lkm_id")
private Long lkmId; //联系人编号(主键)
@Column(name = "lkm_name")
private String lkmName;//联系人姓名
@Column(name = "lkm_gender")
private String lkmGender;//联系人性别
@Column(name = "lkm_phone")
private String lkmPhone;//联系人办公电话
@Column(name = "lkm_mobile")
private String lkmMobile;//联系人手机
@Column(name = "lkm_email")
private String lkmEmail;//联系人邮箱
@Column(name = "lkm_position")
private String lkmPosition;//联系人职位
@Column(name = "lkm_memo")
private String lkmMemo;//联系人备注
/**
* 配置联系人到客户的多对一关系
* 使用注解的形式配置多对一关系
* 1.配置表关系
* @ManyToOne : 配置多对一关系
* targetEntity:对方的实体类字节码
* 2.配置外键(中间表)
*
* * 配置外键的过程,配置到了多的一方,就会在多的一方维护外键
*
*/
@ManyToOne(targetEntity = Customer.class,fetch = FetchType.LAZY)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Customer customer;
set/get
}
在配置实体类(多的一方)时应该注意到的
在我看来没什么需要注意的,只要正常配置就好。
对象导航查询
查询一个对象的同时,通过此对象查询他的关联对象
从一方查询多方
- 默认:使用延迟加载
从多方查询一方
- 默认:使用立即加载