1.JPA中的一对多

在一对多关系中,我们习惯把一的一方称之为主表,把多的一方称之为从表。在数据库中建立一对多的关系,需要使用数据库的外键约束。

什么是外键?

指的是从表中有一列,取值参照主表的主键,这一列就是外键。

2. 实体类关系建立以及映射配置

在实体类中,由于客户是少的一方,它应该包含多个联系人,所以实体类要体现出客户中有多个联系人的信息,代码如下:

一的一方Customer

/**
* 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<>();

多的一方LinkMan

@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;

3.映射的注解说明

@OneToMany:

作用:建立一对多的关系映射

属性:

targetEntityClass:指定多的多方的类的字节码

mappedBy:指定从表实体类中引用主表对象的名称。

cascade:指定要使用的级联操作

fetch:指定是否采用延迟加载

orphanRemoval:是否使用孤儿删除

@ManyToOne

作用:建立多对一的关系

属性:

targetEntityClass:指定一的一方实体类字节码

cascade:指定要使用的级联操作

fetch:指定是否采用延迟加载

optional:关联是否可选。如果设置为false,则必须始终存在非空关系。

@JoinColumn

作用:用于定义主键字段和外键字段的对应关系。

属性:

name:指定外键字段的名称

referencedColumnName:指定引用主表的主键字段名称

unique:是否唯一。默认值不唯一

nullable:是否允许为空。默认值允许。

insertable:是否允许插入。默认值允许。

updatable:是否允许更新。默认值允许。

columnDefinition:列的定义信息。

4.JPA中的一对多测试

RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class OneToManyTest { @Autowired
private CustomerDao customerDao; @Autowired
private LinkManDao linkManDao; /**
* 保存一个客户,保存一个联系人
* 效果:客户和联系人作为独立的数据保存到数据库中
* 联系人的外键为空
* 原因?
* 实体类中没有配置关系
*/
@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);
} /**
* 会有一条多余的update语句
* * 由于一的一方可以维护外键:会发送update语句
* * 解决此问题:只需要在一的一方放弃维护权即可
*
*/
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testAdd2() {
//创建一个客户,创建一个联系人
Customer customer = new Customer();
customer.setCustName("百度"); LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李"); linkMan.setCustomer(customer);//由于配置了多的一方到一的一方的关联关系(当保存的时候,就已经对外键赋值)
customer.getLinkMans().add(linkMan);//由于配置了一的一方到多的一方的关联关系(发送一条update语句) customerDao.save(customer);
linkManDao.save(linkMan);
}
}

5.级联操作

级联操作:指操作一个对象同时操作它的关联对象

使用方法:只需要在操作主体的注解上配置cascade

/**
* cascade:配置级联操作
* CascadeType.MERGE 级联更新
* CascadeType.PERSIST 级联保存:
* CascadeType.REFRESH 级联刷新:
* CascadeType.REMOVE 级联删除:
* CascadeType.ALL 包含所有
*/
@OneToMany(mappedBy="customer",cascade=CascadeType.ALL)

6.级联添加和级联删除

/**
* 级联添加:保存一个客户的同时,保存客户的所有联系人
* 需要在操作主体的实体类上,配置casacde属性
*/
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testCascadeAdd() {
Customer customer = new Customer();
customer.setCustName("百度1"); LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李1"); linkMan.setCustomer(customer);
customer.getLinkMans().add(linkMan); customerDao.save(customer);
} /**
* 级联删除:
* 删除1号客户的同时,删除1号客户的所有联系人
*/
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testCascadeRemove() {
//1.查询1号客户
Customer customer = customerDao.findOne(1l);
//2.删除1号客户
customerDao.delete(customer);
}

                                                                                       ————你是我自罚三杯也不能开口的秘密

最新文章

  1. yii2.0场景的使用
  2. caffe pytho接口
  3. easyui 中Datagrid 控件在列较多且无数据时,列显示不全的解决方案
  4. windows下安装使用Composer记录
  5. ubuntu 无声音的解决
  6. [转]RamDisk导致远程桌面客户端无法启动问题
  7. gradle教程 [原创](eclipse/ADT下 非插件 非Android Studio/AS)纯手打 第一篇:安装配置gradle
  8. [Asp.net mvc]实体更新异常:存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。
  9. 6 个轻量级并且灵活的 PHP CMS 系统
  10. eclipse中Java代码导入包,出现main.java前缀
  11. Linux搭建Tomcat
  12. HTML移动端开发常见的兼容性总结
  13. php中自动加载类_autoload()和spl_autoload_register()实例详解
  14. Azure SQL Database (24) 使用新管理界面,创建跨数据中心标准地域复制(Standard Geo-Replication)
  15. document.getElementById动态的Node集合随时变化, 和document.querySelector静态的后续无法变化
  16. 《程序设计入门——C语言》翁恺老师 第四周编程练习记录
  17. Swift 通过字符串创建控制器
  18. Linux学习笔记 11
  19. 转载 互斥体与互锁 &lt;第五篇&gt;
  20. Atitit 项目管理 提升开发效率的项目流程方法模型 哑铃型 &#160;橄榄型 直板型

热门文章

  1. 如何在Spring Boot 中动态设定与执行定时任务
  2. webService服务简单实现
  3. Docker搭建Portainer可视化界面
  4. n-map安装实操
  5. codis 使用
  6. Dribbble 流行的配色风格是什么?
  7. The linux command 之软件包管理
  8. CF698F Coprime Permutation
  9. python3文件方法
  10. bootstrap1总结