Hibernate入门六(单项的保存操作)

package com.itheima12.hibernate.onetomanysingle;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.itheima12.hibernate.domain.Classes;
import com.itheima12.hibernate.domain.Student;
import com.itheima12.hibernate.utils.HibernateUtils;

/**
 * 一对多的单项
 * @author zd
 *              一般操作
                1、保存班级
                2、保存学生
                3、保存班级,保存学生

                级联操作
                4、保存班级级联保存学生
                5、保存班级级联更新学生
                6、更新班级级联保存学生
                7、更新班级级联更新学生
                8、删除班级级联删除学生
                9、在班级有级联save-update的情况下,从关联得到学生,并且删除学生?

                关系操作
                8、已经存在一个班级,新建一个学生,把该学生加入到该班级(建立关系操作)
                9、已经存在一个学生,新建一个班级,把该学生加入到该班级(建立关系操作)
                10、已经存在一个学生,已经存在一个班级,把该学生加入到该班级
                11、已经存在一个学生,把一个学生从一个班级转移到另外一个班级

                在一的一方维护关系的时候,总会发出维护关系的update语句,该update语句就是更新外键

                级联和关系的混合:
                12、在删除班级的时候,解除班级和学生之间的关系
 */
public class OneToManySingleTest extends HibernateUtils{
    @Test
    //保存一个班级对象
    public void testSaveClasses(){
    //我继承自HibernateUtils 我就能直接调用getCurrentSession
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        Classes classes = new Classes();
        classes.setName("黑马JavaEE+hadoop的12期");
        classes.setDescription("牛");
        session.save(classes);
        transaction.commit();
    }

    @Test
    //保存一个学生对象
    public void testSaveStudent(){
    //我继承自HibernateUtils 我就能直接调用getCurrentSession
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Student student = new Student();
        student.setName("班长");
        student.setDescription("带头大哥");
        session.save(student);
        transaction.commit();
    }

    @Test
    //想保存一个班级和学生
    public void testSaveClassesAndSaveStudent(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        Classes classes = new Classes();
        classes.setName("黑马视频班");
        classes.setDescription("野牛");

        Student student = new Student();
        student.setName("班秘");
        student.setDescription("凤姐");
        //保存两次
        session.save(classes);
        session.save(student);
        transaction.commit();
    }

这里写图片描述
这个运行起来 还是没有关联起来,而且一般不这么做,因为假设有100个学生对象的话,save100次。。。。
如果想要是进行级联操作的话,需要配置classess的配置文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.itheima12.hibernate.domain.Classes">
        <id name="cid" length="5">
            <generator class="increment"></generator>
        </id>
        <property name="description" length="50"></property>
        <property name="name" length="20"></property>
        <!-- 
            set元素针对的就是Classes类中的Set属性
            cascade  级联操作
               null  默认值
               save-update
                    在保存classes对象的时候,针对student进行保存或者更新的操作
                    在更新classes对象的时候,针对student进行保存或者更新的操作
               all
               delete
            inverse  关系操作
               default:classes维护classes与student之间的关系
               true:   classes不维护classes与student之间的关系
               false:  classes维护classes与student之间的关系
         -->
        <set name="students" cascade="save-update" inverse="true">
            <!-- 
                外键
                    告诉hibernate,通过cid就可以建立classes与student之间的关联
             -->
            <key>
                <column name="cid"></column>
            </key>
            <!-- 
                告诉hibernate,Classes类中的set集合中存放的是哪个元素
             -->
            <one-to-many class="com.itheima12.hibernate.domain.Student"/>
        </set>
    </class>
</hibernate-mapping>

配置好xml文件以后,继续编写测试类

    /**

     * 在保存班级的时候,级联保存学生
     */
    @Test
    public void testSaveClasses_Cascade_Save_Student(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Classes classes = new Classes();
        classes.setName("黑马视频班");
        classes.setDescription("野牛");

        Student student = new Student();
        student.setName("班秘");
        student.setDescription("凤姐");

        //建立classes与student之间的关联 但是如果在xml文件中没有配置 级联的话就会出现错误
        //我先准备一个set集合 
        Set<Student> students = new HashSet<Student>();
        students.add(student);
        classes.setStudents(students);

        session.save(classes); //显示保存的是classes,把保存student称为隐式保存
        //这里有个很难排 transient 临时的 

        transaction.commit();
    }

    /**
     * 在更新班级的时候,级联更新学生
     * sessin.flush的时候
     *    1、检查一级缓存中所有的持久化状态的对象
     *        判断发出insert语句或者update语句
     *    2、检查所有的持久化对象的关联对象
     *         如果关联对象是由临时状态转化过来的,则对关联对象发出insert语句
     *         如果关联对象是从数据库中提取出来的,则对照副本,决定是否发出update语句
     */
    @Test
    public void testUpdateClasses_Cascade_Update_Student(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Classes classes = (Classes)session.get(Classes.class, 2L);//持久化类
        Set<Student> students = classes.getStudents();//持久化类   
        for (Student student : students) {//把每一个student对象(关联对象)也放入到了一级缓存中
            student.setDescription("bb");
        }
         students = classes.getStudents();//再次执行的话 发现并没有发出sql语句 说明  
        for (Student student : students) {//把每一个student对象(关联对象)也放入到了一级缓存中
            student.setDescription("bb");
        }
        transaction.commit();
    }

这里写图片描述

    /**
     * 在更新班级的时候,添加学生
     */
    @Test
    public void testUpdateClasses_Cascade_Save_Student(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        /*
         * 给cid为2的班级添加一个学生
         */
         //首先我得得到cid为2的班级 
        Classes classes = (Classes)session.get(Classes.class, 2L);
        //接下来我得整一个学生
        Student student = new Student();
        student.setName("美女1");
        student.setDescription("小林志玲");

        /**
         * 建立班级与学生的关联
         * Set<Student> students = new HashSet<Student>();
         * students.add(student);
         * 这个不行 会全覆盖 涉及到了关系操作
         */
        classes.getStudents().add(student);

        transaction.commit();
    }

总结一下:在保存或者更新班级的时候,我操作学生
    /**
     * 在更新班级的时候,级联保存学生,并且维护关系
     *  Hibernate: 
            select
                classes0_.cid as cid0_0_,
                classes0_.description as descript2_0_0_,
                classes0_.name as name0_0_ 
            from
                Classes classes0_ 
            where
                classes0_.cid=?
        Hibernate: 
            select
                students0_.cid as cid0_1_,
                students0_.sid as sid1_,
                students0_.sid as sid1_0_,
                students0_.description as descript2_1_0_,
                students0_.name as name1_0_ 
            from
                Student students0_ 
            where
                students0_.cid=?
        Hibernate: 
            select
                max(sid) 
            from
                Student
        Hibernate: 
                   因为在Classes.hbm.xml文件中设置了级联
                 <set name="students" cascade="save-update">
            insert 
            into
                Student
                (description, name, sid) 
            values
                (?, ?, ?)
        Hibernate: 
                   因为在Classes.hbm.xml文件中,inverse没有写,默认classes维护classes与student之间的关系
                   所以发出了更新关系的update语句 怎么体现维护关系 通过更新外键关系
                   这个语句发出的关键是 inverse 
            update
                Student 
            set
                cid=? 
            where
                sid=?
     */
    @Test
    public void testUpdateClasses_Cascade_Save_Student_Inverse(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        /*
         * 给cid为2的班级添加一个学生
         */
        Classes classes = (Classes)session.get(Classes.class, 2L);

        Student student = new Student();
        student.setName("美女1");
        student.setDescription("小林志玲");

        /**
         * 建立班级与学生的关联
         */
        classes.getStudents().add(student);

        transaction.commit();
    }

    /**
     * 已经存在一个班级cid为1,已经存在一个学生,已经存在另外一个班级cid为2,该学生从cid为1的班级转到cid为2的班级
     */
    @Test
    public void testTransform(){
        /**
         * 1、把cid为1,2和sid为1的对象提取出来
         */
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        //Classes classes1 = (Classes)session.get(Classes.class, 1L);
        Classes classes2 = (Classes)session.get(Classes.class, 2L);//发出查询的sql语句
        Student student = (Student)session.get(Student.class, 1L);//发出查询的sql语句

        //解除 classes1与student之间的关系
        //classes1.getStudents().remove(student);
        //建立classes2与student之间的关系
        classes2.getStudents().add(student);
        transaction.commit();
    }

    /**
     * 解除该班级和该班级中的所有的学生之间的关系
     */
    @Test
    public void testRealseR(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        /**
         * 解除cid为2的班级和所有的学生之间的关系
         */
        Classes classes = (Classes)session.get(Classes.class,2L);
        classes.setStudents(null);
        transaction.commit();
    }

    /**
     * 解除该班级和所有的学生之间的关系,再建立该班级和一些学生之间的关系
     */
    @Test
    public void testRealseAllR_BuildSomeR(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //解除cid为2的班级和所有的学生之间的关系
        Classes classes = (Classes)session.get(Classes.class, 2L);
        classes.setStudents(null);

        Student student1 = new Student();
        student1.setName("王二麻子");

        Student student2 = new Student();
        student2.setName("隔壁老李");
        Set<Student> students = new HashSet<Student>();
        students.add(student2);
        students.add(student1);
        classes.setStudents(students);

        transaction.commit();
    }

    /**
     * 删除一个班级
     *   在删除班级之前,解除班级和学生之间的关系
     *   Hibernate: 
            select
                classes0_.cid as cid0_0_,
                classes0_.description as descript2_0_0_,
                classes0_.name as name0_0_ 
            from
                Classes classes0_ 
            where
                classes0_.cid=?
        Hibernate: 
                   因为classes负责维护关系,所以该语句就是解除关系的sql语句
            update
                Student 
            set
                cid=null 
            where
                cid=?
        Hibernate: 
            delete 
            from
                Classes 
            where
                cid=?

     */
    @Test
    public void testDeleteClasses_1(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Classes classes = (Classes)session.get(Classes.class, 1L);
        session.delete(classes);
        transaction.commit();
    }

    /**
     * 在 Classes.hbm.xml文件中
     *     <set name="students" cascade="all">
     *     在删除班级的时候,级联删除学生
     */
    @Test
    public void testDeleteClasses_2(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Classes classes = (Classes)session.get(Classes.class, 1L);
        session.delete(classes);
        transaction.commit();
    }

    /**
     * 删除一个学生,但是该学生必须从班级中提取出来
     *   因为在Classes.hbm.xml文件中
     *      <set name="students" cascade="save-update">
     *      classes针对student是关联的
     *      而程序中的student对象是从classes中提取出来的关联对象,所以不能删除
     */
    @Test
    public void testError(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Classes classes = (Classes)session.get(Classes.class, 1L);
        Set<Student> students = classes.getStudents();
        //classes.setStudents(null);//解除关系
        for (Student student : students) {
            session.delete(student);
        }
        transaction.commit();
    }
}

这里来解释一下:为什么每次执行都跟着一个update语句
这里写图片描述
我要建立联系班级和学生的联系,在hibernate面向对象操作,cascade是级联操作,hibernate当中有个属性叫做inverse
inverse 关系操作

  • default:classes维护classes与student之间的关系
  • true: classes不维护classes与student之间的关系
  • false: classes维护classes与student之间的关系
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值