JPA级联查询

客户 :指一家公司,可以有多个联系人  与联系人是一对多关系
联系人: 只属于一家公司 与客户是多对一关系
 
客户表
public class Customer {

/**
* @Id:声明主键的配置
* @GeneratedValue:配置主键的生成策略
* strategy
* GenerationType.IDENTITY :自增,mysql
* * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
* GenerationType.SEQUENCE : 序列,oracle
* * 底层数据库必须支持序列
* GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
* GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
* @Column:配置属性和字段的映射关系
* name:数据库表中字段的名称
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId; //客户的主键

@Column(name = "cust_name")
private String custName;//客户名称

@Column(name="cust_source")
private String custSource;//客户来源

@Column(name="cust_level")
private String custLevel;//客户级别

@Column(name="cust_industry")
private String custIndustry;//客户所属行业

@Column(name="cust_phone")
private String custPhone;//客户的联系方式

@Column(name="cust_address")
private String custAddress;//客户地址

/**
* 配置一对多关系
* 使用注解方式
* 1.声明关系 @OneToMany 表示一对多关系
* 2. 配置外键(中间表)
* @JoinColumn: 配置外键
* name: 外键字段名称
* referencedColumnName:参照主表的主键字段名称
* 在客户实体类上 添加了外键配置,所以对于客户而言,也具备了维护外键的作用
*/
@OneToMany(targetEntity = LinkMan.class)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Set<LinkMan> linkMans = new HashSet<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)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Customer customer;

测试代码

  @Test
    @Transactional
    @Rollback(false)
    public  void testAff(){
        //创建一个客户
        Customer customer = new Customer();
        customer.setCustName("百度");

        LinkMan linkMan = new LinkMan();
        linkMan.setLkmName("小李");
        /*LinkMan linkMan2 = new LinkMan();
        linkMan.setLkmName("小李2");*/
        customer.getLinkMans().add(linkMan);
        customerDao.save(customer);
        linkManDao.save(linkMan);

    }

运行之后可以在表中看到link _man 表中lkm_cust_id 会有外键

 

 说明实体之间已经建立联系,也就是外键维护

如果没有这一行

customer.getLinkMans().add(linkMan);

是不会生成外键

实际上看控制台会知道 执行了两条insert语句 以及一条update 更新外键的语句

 

 这里是通过客户维护到联系人 同样联系人也可以维护到客户 却只有两条insert语句

    @Test
    @Transactional
    @Rollback(false)
    public  void testAff01(){
        //创建一个客户
        Customer customer = new Customer();
        customer.setCustName("百度");

        LinkMan linkMan = new LinkMan();
        linkMan.setLkmName("小李");

        linkMan.setCustomer(customer);
        customerDao.save(customer);
        linkManDao.save(linkMan);

    }

 

 

 同样都能到达效果,但 多对一中 一的一方会维护外键 多了update语句 

 所以一般情况下 会放弃一的一方放弃维护权

 

 题外:实体上我用的@Data 但是测试时会报错,就换成了@Setter @Getter ???

 

 删除主表数据

      1. 默认情况下从表数据会把外键设置为null,然后删除主表数据,如果有非空约束,则报错

       2.  如果放弃了维护关联关系,则不能删除(于外键是否为空,没有关系),因为在删除时根本不会去更新从表的外键字段

       3. 如果非要删除,使用级联删除引用

 级联 :

          操作一个对象的同时操作他的关联对象

          1.需要区分操作的主体

          2.需要在主体上添加级联属性(注解)  -------cascade

 

 

 

@Test
    @Transactional
    @Rollback(false)
    public  void testAff02(){
        //创建一个客户
        Customer customer = new Customer();
        customer.setCustName("百度");

        LinkMan linkMan = new LinkMan();
        linkMan.setLkmName("小李");

        linkMan.setCustomer(customer);
        customer.getLinkMans().add(linkMan);

        customerDao.save(customer);

    }

去掉了

linkManDao.save(linkMan);

删除

cascada  

CascadeType {
all 所以
MERGE 更新
persist 保存
remove 删除
}

需要之前的create 改为 update

 

 

@Test
    @Transactional
    @Rollback(false)
    public  void testAff03(){

        Customer customer = customerDao.getOne((long) 1);

        customerDao.delete(customer);


    }

 

 

 

 

posted @ 2020-11-24 20:49  SoToHard  阅读(521)  评论(0编辑  收藏  举报