基与上一篇文章 Specifications 接口动态查询入门小 demo , 我们继续深入
一. 创建联系人表(与顾客表是多对一关系)
/*创建联系人表*/
CREATE TABLE cst_linkman (
lkm_id BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
lkm_name VARCHAR(16) DEFAULT NULL COMMENT '联系人姓名',
lkm_gender CHAR(1) DEFAULT NULL COMMENT '联系人性别',
lkm_phone VARCHAR(16) DEFAULT NULL COMMENT '联系人办公电话',
lkm_mobile VARCHAR(16) DEFAULT NULL COMMENT '联系人手机',
lkm_email VARCHAR(64) DEFAULT NULL COMMENT '联系人邮箱',
lkm_position VARCHAR(16) DEFAULT NULL COMMENT '联系人职位',
lkm_memo VARCHAR(512) DEFAULT NULL COMMENT '联系人备注',
lkm_cust_id BIGINT(32) NOT NULL COMMENT '客户id(外键)',
PRIMARY KEY (`lkm_id`),
KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),
CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
二. 创建数据库中联系人表的实体类
package com.cast.domain;
import java.io.Serializable;
import javax.persistence.*;
/**
* 封装数据库中表的实体类
*/
@Entity //该类是一个数据库表实体封装类
@Table(name = "cst_linkman") //指定数据库中对应表名
public class Customer implements Serializable {
@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; //联系人备注
/**
* 配置联系人到客户的多对一关系
*/
@ManyToOne(targetEntity = Customer.class, fetch = FetchType.LAZY)
@JoinColumn(name = "lkm_cust_id", referencedColumnName = "cust_id")
private Customer customer;
// getter setter 方法....
// toString() 方法....
}
三. 创建符合 SpringDataJpa 的 dao 层接口规范
public interface LinkManDao extends JpaRepository<LinkMan, Long>, JpaSpecificationExecutor<LinkMan> {
}
四.Customer 封装类中添加一对多的注解配置
@OneToMany(targetEntity = LinkMan.class)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Set<LinkMan> linkMans = new HashSet<>();
五. 创建新的测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class OneToManyTest {
@Autowired
private CustomerDao customerDao;
@Autowired
private LinkManDao linkManDao;
}
1. 添加数据的方法
配置客户到联系人的关系:
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testAddByCustomer() {
//创建一个客户
Customer customer = new Customer();
customer.setCustName("张三");
customer.setCustAddress("武汉市汉阳区");
//创建一个联系人
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李");
linkMan.setLkmPhone("1313131313");
//配置客户到联系人的关系
customer.getLinkMans().add(linkMan);
customerDao.save(customer);
linkManDao.save(linkMan);
}
配置联系人到客户的关系:
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testAddByLinkman() {
//创建一个客户
Customer customer = new Customer();
customer.setCustName("张三");
customer.setCustAddress("武汉市汉阳区");
//创建一个联系人
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李");
linkMan.setLkmPhone("1313131313");
//配置联系人到客户的关系
linkMan.setCustomer(customer);
customerDao.save(customer);
linkManDao.save(linkMan);
}
以下操作会产生一条重复更新的 sql 语句:
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testAdd() {
//创建一个客户
Customer customer = new Customer();
customer.setCustName("张三");
customer.setCustAddress("武汉市汉阳区");
//创建一个联系人
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李");
linkMan.setLkmPhone("1313131313");
//配置客户到联系人
customer.getLinkMans().add(linkMan);
//配置联系人到客户
linkMan.setCustomer(customer);
customerDao.save(customer);
linkManDao.save(linkMan);
}
客户放弃关联外键可解决该问题:
*** mappedBy 的值为 联系人封装类中定义的 Customer 的成员变量
//@OneToMany(targetEntity = LinkMan.class)
//@JoinColumn(name = "lkm_cust_id", referencedColumnName = "cust_id")
@OneToMany(mappedBy = "customer") //放弃关联外键维护权 配置此注解
private Set<LinkMan> linkMans = new HashSet();
2. 级联添加: 保存客户的同时, 也保存该客户关联的联系人
* 在客户封装联系人类中的成员属性上修改注解:
(CascadeType.ALL 是级联所有操作)
(CascadeType.MERGE 是级联更新操作)
(CascadeType.PERSIST 是级联保存操作)
(CascadeType.REMOVE 是级联删除操作)
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private Set<LinkMan> linkMans = new HashSet();
* 编写级联添加的方法:
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testCascadeAdd() {
//创建一个客户
Customer customer = new Customer();
customer.setCustName("小张");
customer.setCustAddress("武汉市汉阳区");
//创建一个联系人
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小陈");
linkMan.setLkmPhone("1313131313");
//配置联系人到客户
linkMan.setCustomer(customer);
//配置客户到联系人
customer.getLinkMans().add(linkMan);
customerDao.save(customer);
}
3. 级联删除: 删除客户的同时, 也删除该客户关联的联系人
* 编写级联删除的方法:
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testCascadeDelete() {
//查询到指定 id 客户
Customer customer = customerDao.findOne(1L);
//执行删除该 id 客户
customerDao.delete(customer);
}
源代码下载: https://pan.baidu.com/s/1ovQIFOHe3sT4ROFop4BM1A