HibernateDay03(一对多和多对多 级联删除保存 cascade四种取值 配置文件 )

1、持久化类和一级缓存
    持久化类:JavaBean+映射的配置文件
    持久化对象的三种状态
        瞬时态
        持久态
        脱管态
    Session的一级缓存,快照机制
    主键的生成策略
        常用uuid native

2、管理事务
    设置隔离级别
    丢失更新的问题,乐观锁:添加属性version,配置<version name="version">
    绑定本地的session,事务需要在service层开启,dao层需要使用session对象

3、查询的接口
    Query接口:HQL的查询
    Criteria接口:QBC查询(按条件进行查询)

关联关系映射一对多映射
1、一对多的设计
2、导入SQL的建表语句
    创建数据库
    导入SQL脚本
3、编写客户和联系人的JavaBean程序(一对多的编写规则)

级联保存
1、如果代码只插入其中的一方的数据
    如果只保存其中的一方的数据,那么程序会抛出异常
    如果想完成只保存一方的数据,并且把相关联的数据都保存到数据库中,那么需要配置级联

    级联保存是方向性的
2、级联保存的效果
    级联保存:保存一方的同时可以把关联的对象也保存到数据库中
    使用cascade="save-update"

级联删除
1、含有外键的删除客户功能,那么SQL语句会报错
    delete from customers where cid =1;
2、如果使用Hibernate框架直接删除客户的时候 发现可删除

3、上述的删除是普通的删除,也可以使用级联删除,级联删除有方向性
    <many-to-one cascade="delete"/> 一般都是假删除就加个字段置10表示已删除

cascade的取值和孤儿删除
1、取值
    none                不使用级联
    save-update         级联保存或更新
    delete              级联删除
    delete-orphan       孤儿删除(只能应用在一对多关系)
    all                 除了delete-orphan的所有情况(包含save-update delete)
    all-delete-orphan   包含了delete-orphan的所有情况(包含save-update delete delete-orphan2、孤儿删除(孤子删除)只有在一对多的环境下才有孤儿删除
    在一对多的关系下,可以将一的一方认为是父方,将多的一方认为是子方,孤儿删除:在解除了父子关系的时候,将子方记录就直接删除
    <many-to-one cascade="delete-orphan"/>

某一方放弃外键的维护,为多对多作准备
1、双方都维护外键的时候,会产生多于的SQL语句
    想修改客户和联系人的关系,进行双向关联,双方都会维护外键,会产生多余的SQL语句
    产生的原因:session的一级缓存中的快照机制,会让双方都更新数据库,产生了多余的SQL语句

2、如果不想产生多余的SQL语句,那么需要一方来放弃外键的维护
    在<set>标签上配置一个inverse="true",true:放弃,false:不放弃 默认false
    <inverse="true">    

cascade和inverse的区别
1、cascade用来级联操作(保存或者修改和删除)
    多方 save-update
2、inverse用来维护外键的
    一方放弃维护

级联保存
<set cascade="save-update">

级联删除(在多对多很少使用)
级联删除

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

/**
 * 测试一对多
 * @author Administrator
 *
 */
public class Demo1 {
    /**
     * 双向关联的方式,保存数据
     */
    @Test
    public void run1() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //保存客户和联系人的数据
        Customer c1 = new Customer();
        c1.setCust_name("小明");
        //创建2个联系人
        Linkman l1 = new Linkman();
        l1.setLkm_name("小弟");
        Linkman l2 = new Linkman();
        l2.setLkm_name("大哥");

        //双向关联
        c1.getLinkmans().add(l1);
        c1.getLinkmans().add(l2);

        l1.setCustomer(c1);
        l2.setCustomer(c1);

        //保存数据
        session.save(c1);
        session.save(l1);
        session.save(l2);

        tr.commit();
    }
    /**
     * 单向的关联,如果不配置级联保存,程序出现异常
     */
    @Test
    public void run2() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //保存客户和联系人的数据
        Customer c1 = new Customer();
        c1.setCust_name("小明");
        //创建2个联系人
        Linkman l1 = new Linkman();
        l1.setLkm_name("小弟");
        Linkman l2 = new Linkman();
        l2.setLkm_name("大哥");

        //单向关联
        c1.getLinkmans().add(l1);
        c1.getLinkmans().add(l2);


        //保存数据
        session.save(c1);

        tr.commit();
    }
    /**
     * 级联保存 要去掉原来的表因为修改了表结构
     *  保存客户,级联联系人
     */
    @Test
    public void run3() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //保存客户和联系人的数据
        Customer c1 = new Customer();
        c1.setCust_name("小明");
        //创建2个联系人
        Linkman l1 = new Linkman();
        l1.setLkm_name("小弟");
        Linkman l2 = new Linkman();
        l2.setLkm_name("大哥");

        //单向关联
        c1.getLinkmans().add(l1);
        c1.getLinkmans().add(l2);


        //保存数据
        session.save(c1);

        tr.commit();
    }
    /**
     * 级联保存:保存联系人,保存客户
     */
    @Test
    public void run4() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //保存客户和联系人的数据
        Customer c1 = new Customer();
        c1.setCust_name("小明");
        //创建2个联系人
        Linkman l1 = new Linkman();
        l1.setLkm_name("小弟");
        Linkman l2 = new Linkman();
        l2.setLkm_name("大哥");


        //使用联系人关联客户
        l1.setCustomer(c1);
        l2.setCustomer(c1);

        //保存
        session.save(l1);
        session.save(l2);
        //没有保存l2
        tr.commit();
    }
    @Test
    public void run5() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //保存客户和联系人的数据
        Customer c1 = new Customer();
        c1.setCust_name("小明");
        //创建2个联系人
        Linkman l1 = new Linkman();
        l1.setLkm_name("小弟");
        Linkman l2 = new Linkman();
        l2.setLkm_name("大哥");


        //使用联系人关联客户
        l1.setCustomer(c1);
        c1.getLinkmans().add(l2);
        //保存
        session.save(l1);
        //没有保存l2
        tr.commit();
    }
    /**
     * 删除客户,客户有2个联系人
     * 先把 lkm_cust_id外键置null 
     */
    @Test
    public void run6() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //先查询1号客户
        Customer c1 = session.get(Customer.class, 1L);
        session.delete(c1);
        tr.commit();
    }
    /**
     * 级联删除 删除客户,级联删除客户下的联系人
     */
    @Test
    public void run7() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //先查询1号客户
        Customer c1 = session.get(Customer.class, 1L);
        session.delete(c1);
        tr.commit();
    }
    /**
     * 删除联系人,级联删除客户
     */
    @Test
    public void run8() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //先查询3号联系人
        Linkman l1 = session.get(Linkman.class, 3L);
        session.delete(l1);
        tr.commit();
    }

    /**
     * 测试级联删除
     */
    @Test
    public void run9() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //先查询3号联系人
        Linkman l1 = session.get(Linkman.class, 3L);
        session.delete(l1);
        tr.commit();
    }

    /**
     * 解除关系:从集合中删除联系人
     */
    @Test
    public void run10() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //先获取到客户
        Customer c1 = session.get(Customer.class, 1L);
        Linkman l1 = session.get(Linkman.class, 1L);
        //解除
        c1.getLinkmans().remove(l1);
        tr.commit();
    }
    /**
     * 放弃外键的维护
     * 让小弟联系人属于小风
     */
    @Test
    public void run11() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //先获取到客户
        Customer c2 = session.get(Customer.class, 2L);
        Linkman l1 = session.get(Linkman.class, 1L);

        //做双向关联
        c2.getLinkmans().add(l1);
        l1.setCustomer(c2);
        //不用修改
        tr.commit();
    }
    /**
     * cascade和inverse的区别
     */
    @Test
    public void run12() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =  session.beginTransaction();
        //保存客户和联系人的数据
        Customer c1 = new Customer();
        c1.setCust_name("小明");
        //创建2个联系人
        Linkman l1 = new Linkman();
        l1.setLkm_name("小弟");
        Linkman l2 = new Linkman();
        l2.setLkm_name("大哥");

        //单向关联
        l1.setCustomer(c1);
        l2.setCustomer(c1);


        //保存数据
        session.save(l1);
        session.save(l1);
        tr.commit();
    }

}
public class Demo2 {
    @Test
    public void run1() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        //模拟多对多,双向关联
        User u1 = new User();
        u1.setUsername("zs");
        User u2 = new User();
        u2.setUsername("ls");

        //创建角色
        Role r1 = new Role();
        r1.setRname("小弟");
        Role r2 = new Role();
        r2.setRname("大哥");

        //关联
        u1.getRoles().add(r1);
        u1.getRoles().add(r2);
        r1.getUsers().add(u1);
        r2.getUsers().add(u1);

        u2.getRoles().add(r1);
        r1.getUsers().add(u2);

        session.save(u1);
        session.save(u2);
        session.save(r1);
        session.save(r2);

        tr.commit();
    }

    @Test
    public void run2() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        //模拟多对多,双向关联
        User u1 = new User();
        u1.setUsername("zs");
        User u2 = new User();
        u2.setUsername("ls");

        //创建角色
        Role r1 = new Role();
        r1.setRname("小弟");
        Role r2 = new Role();
        r2.setRname("大哥");

        u1.getRoles().add(r1);
        u1.getRoles().add(r2);
        u2.getRoles().add(r1);

        //保存数据
        session.save(u1);
        session.save(u2);

        tr.commit();
    }

    /**
     * 张三用户,2个角色,大哥和小弟
     * 让张三没有演员角色
     */
    @Test
    public void run3() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();

        //查询张三用户
        User u1 = session.get(User.class, 1L);
        //查询角色
        Role r2 = session.get(Role.class,2L);
        u1.getRoles().remove(r2);

        tr.commit();
    }
}

Dao.Customer

public class CustomerDao {

    /**
     * 保存客户
     */
    public void save(Customer c) {
        //先获取session
        Session session = HibernateUtils.getSession();
        //开启事务
        Transaction tr = session.beginTransaction();
        //保存用户
        session.save(c);
        //提交事务
        tr.commit();
        //关闭资源
        session.close();
    }

    /**
     * 查询所有的客户
     */
    public List<Customer> findAll(){
        //QBC查询
        Session session = HibernateUtils.getSession();
        Transaction tr = session.beginTransaction();

        //查询
        Criteria criteria = session.createCriteria(Customer.class);
        //查询
        List<Customer> list = criteria.list();
        tr.commit();
        session.close();
        return list;
    }

    /**
     * 带查询条件的查询所有的客户
     */
    public List<Customer> findAll(String custName){
        //QBC查询
        Session session = HibernateUtils.getSession();
        Transaction tr = session.beginTransaction();

        //查询
        Criteria criteria = session.createCriteria(Customer.class);

        //添加查询的条件
        if(custName != null && !custName.trim().isEmpty()) {
            //添加查询条件
            criteria.add(Restrictions.like("cust_name", "%"+custName+"%"));
        }

        //查询
        List<Customer> list = criteria.list();
        tr.commit();
        session.close();
        return list;
    }

    /**
     * 通过主键查询客户
     * @param cust_id
     * @return
     */
    public Customer findById(Long cust_id) {
        //使用session
        Session session = HibernateUtils.getCurrentSession();
        //查询
        return session.get(Customer.class, cust_id);
    }
}

Dao.Linkman

public class LinkmanDao {

    /**
     * 保存联系人
     * @param man
     */
    public void save(Linkman man) {
        Session session = HibernateUtils.getCurrentSession();
        System.out.println(man.toString());
        session.save(man);
    }

}

Domain.Linkman

public class Linkman {
    /**
  `lkm_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
  `lkm_name` VARCHAR(16) DEFAULT NULL COMMENT '联系人姓名',
  `lkm_cust_id` BIGINT(32) NOT NULL COMMENT '客户id',
  `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_qq` VARCHAR(16) DEFAULT NULL COMMENT '联系人qq',
  `lkm_position` VARCHAR(16) DEFAULT NULL COMMENT '联系人职位',
  `lkm_memo` VARCHAR(512) DEFAULT NULL COMMENT '联系人备注',
     */
    private Long lkm_id;
    private String lkm_name;
    private String lkm_cust_id;
    private String lkm_gender;
    private String lkm_phone;
    private String lkm_mobile;
    private String lkm_email;
    private String lkm_qq;
    private String lkm_position;
    private String lkm_memo;

系统角色

/**
 * 系统角色
 * @author Administrator
 *
 */
public class Role {
    private Long rid;
    private String rname;

    private Set<User> users = new HashSet<User>();

    public Set<User> getUsers() {
        return users;
    }
    public void setUsers(Set<User> users) {
        this.users = users;
    }
/**
 * 系统角色
 * @author Administrator
 *
 */
public class User {
    private Long uid;
    private String username;
    private String password;

    //编写的都是集合
    private Set<Role> roles = new HashSet<Role>();

Customer.hbm.xml

        <!-- 配置一方 -->
        <!-- 
            set标签name属性,表示集合的名称
            一方对应的人多 每个都维护一遍还是让多方维护比较省力
         -->
        <set name="linkmans" inverse="true">
            <!-- 需要出现子标签 -->
            <!-- 外键的字段 -->
            <key column="lkm_cust_id"></key>
            <one-to-many class="my.domain.Linkman"/>
        </set>  

Linkman.hbm.xml

        <!-- 先配置多方 
            name    当前javabean中的属性
            class   属性的全路径
            column  外键的字段
        -->
        <many-to-one name="Customer" class="my.domain.Customer" column="lkm_cust_id" cascade="save-update"/>

role.hbm.xml

        <!-- 配置一方 -->
        <!-- 
            set标签name属性,表示集合的名称
            一方对应的人多 每个都维护一遍还是让多方维护比较省力
         -->
         <!-- 多对多必须有一方放弃外键的维护 -->
        <set name="users" table="sys_user_role" inverse="true">
            <key column="rid"/>
            <many-to-many class="my.domain.User" column="uid"/>
        </set>  

User.hbm.xml

        <!-- 配置多对多
            name    集合的名称
            table   中间表的名称
         -->
        <set name="roles" table="sys_user_role" cascade="save-update">
            <!-- 当前对象在中间表的外键名称 -->
            <key column="uid"></key>
            <!-- 
                class   集合中存入对象,对象的全路径
                column  集合中对象在中间表的外键名称
             -->
            <many-to-many class="my.domain.Role" column="rid"/>
        </set>  

LinkmanService

public class LinkmanService {

    /**
     * 编写业务,保存联系人
     * 先把客户查询出来,设置到联系人中,再保存联系人
     * @param man
     * @param cust_id
     */
    public void save(Linkman man, Long cust_id) {
        //获取session
        Session session = HibernateUtils.getCurrentSession();
        //开启事务
        Transaction tr = session.beginTransaction();
        try {
            //编写代码
            //先查客户
            Customer c = new CustomerDao().findById(cust_id);
            //设置
            man.setCustomer(c);
            //保存联系人
            new LinkmanDao().save(man);
            tr.commit();
        } catch(Exception e) {
            tr.rollback();
            e.printStackTrace();
        }
    }

}

Servlet.initAdd

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //查询所有的客户
        List<Customer> list = new CustomerService().findAll();
        //保存request
        request.setAttribute("list", list);
        request.getRequestDispatcher("/jsp/linkman/add.jsp").forward(request, response);
    }

ServletAddLinkman

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //先解决中文乱码
        request.setCharacterEncoding("utf-8");
        //接受数据
        Map<String,String[]> map = request.getParameterMap();
        //先把客户的id获取到
        String scust_id = map.get("cust_id")[0];
        //转换
        Long cust_id = Long.parseLong(scust_id);

        //封装数据
        Linkman man = new Linkman();
        try {
            //有对应的属性就封装上,没有就null
            BeanUtils.populate(man, map);
            //调用业务层,保存联系人
            new LinkmanService().save(man,cust_id);
            System.out.println(man);
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值