• Hibernate笔记一


    背景

     jdbc的优缺点

      A:直接操作底层,提供了简单,便捷的访问数据库方法,跨平台比较强,灵活,可以写很多赋值的SQL语句;是最底层的数据库操作,所以效率比较高,Sql语句可以自己选择写,采用效率最高的

      B:因为Java是面向对象的,JDBC没有做到使数据能够面向对象的编程,使程序员的思考仍然停留在SQL语句上面,操作繁琐,

         很多代码需要重复写好多次,如果遇到批量操作,繁琐与数据库的交互,容易造成效率的下降

         代码结构比较繁琐,面向纯sql语句的编程,面向过程的编程,对于查询而言,只要查询数据库的一张表,必须有如下的编码:Jdbc技术没有做到数据缓存

         因为事务是自动开启的,所以可能存在安全性的隐患

    JDBC从程序操作可以封装一些什么内容:

    JDBC从程序操作不可以封装一些什么内容:

    Hibernate

     2.1:优点:

    是一个ormapping框架,是一个操作数据库的框架

    面向对象编程的

    代码编程比较简单

    Hibernate做到了数据缓存

    Hibernate用得场合最多的情况是企业中的中小型项目

    2.2:缺点:

    该框架程序员是没有办法干预sql语句的生成的

    如果一个项目中,对sql语句的优化的要求比较高,这个时候不能用hibernate来做

    表之间的关系很复杂的情况下,不能用hibernate来操作

    如果一张表的数据超过了千万级别也不适合用hibernate来做

     分拣:ETL数据抽取

    2.3持久化类:

    2.4:映射文件:

    数据库有多少张表,至少应该有多少个映射文件。

    2.5:配置文件:

           完成数据库的链接信息的填写

    一般有一个

    Hibernate入门操作

    创建一个java project

    1.准备jar包

    2.创建hibernate的配置文件:

     1 <?xml version='1.0' encoding='utf-8'?>
     2 <!DOCTYPE hibernate-configuration PUBLIC
     3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
     4         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
     5 <hibernate-configuration>
     6     <!-- 
     7         一个session-factory代表一个数据库
     8      -->
     9 <session-factory>
    10     <!-- 
    11         链接数据库的用户名
    12     -->
    13     <property name="connection.username">root</property>
    14     <!-- 
    15         链接数据库的密码
    16     -->
    17     <property name="connection.password">root</property>
    18     <!-- 
    19         链接数据库的驱动
    20     -->
    21     <property name="connection.driver_class">
    22         com.mysql.jdbc.Driver
    23     </property>
    24     <!-- 
    25         链接数据库的url
    26     -->
    27     <property name="connection.url">
    28         jdbc:mysql://localhost:3306/itheima09_hibernate
    29     </property>
    30     <!-- 
    31         方言
    32         告诉hibernate用什么样的数据库
    33     -->
    34     <property name="dialect">
    35         org.hibernate.dialect.MySQLDialect
    36     </property>
    37     <!-- 
    38         validate 加载hibernate时,验证数据库的结构
    39         update  加载hibernate时,检查数据库,如果表不存在,则创建,如果存在,则更新
    40         create  每次加载hiberante,都会创建表
    41         create-drop  每次加载hiberante,创建,卸载hiberante时,销毁
    42     -->
    43     <property name="hbm2ddl.auto">update</property>
    44     <!-- 
    45         显示sql语句
    46      -->
    47     <property name="show_sql">true</property>
    48     <!-- 
    49         格式化sql语句
    50      -->
    51     <property name="format_sql">true</property>
    52     <!-- 
    53         加载映射文件
    54     -->
    55     <mapping resource="com/itheima09/hibernate/domain/Person.hbm.xml" />
    56 </session-factory>
    57 </hibernate-configuration>
    Hibernate.cfg.xml

    3.创建hibernate的持久化类:

    Customer.java

     

    说明:持久化类中必须有一个默认的构造器

    4.创建映射文件:

    Customer.hbm.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <!-- 
     6         描述一个持久化类
     7          name属性为持久化类的全名
     8          table 该持久化类对应的表名  默认情况下为类名
     9          catalog 为数据库的名称
    10      -->
    11     <class name="com.itheima09.hibernate.domain.Person" table="pereson">
    12         <!-- 
    13             id对应表中的主键
    14               name为持久化类中属性的名称
    15               length 为对应数据库表中相应字段的长度
    16               column  属性的名称对应的表的字段名称   不写则默认和属性的名称一致
    17          -->
    18         <id name="pid" length="5" type="java.lang.Long" column="pid">
    19             <!-- 
    20                 主键的生成器
    21              -->
    22             <generator class="increment"></generator>
    23         </id>
    24         <property name="name" column="name" type="java.lang.String" length="20">
    25         </property>
    26         <property name="description" column="description" type="java.lang.String" length="50">
    27         </property>
    28     </class>
    29 </hibernate-mapping>
    Person.hbm.xml

    说明:

    从图中可以看出,该映射文件完成了从类到表、类中的属性到表中的字段的对应关系。

     操作数据库:

     1 import java.util.List;
     2 
     3 import org.hibernate.Session;
     4 import org.hibernate.SessionFactory;
     5 import org.hibernate.Transaction;
     6 import org.hibernate.cfg.Configuration;
     7 import org.hibernate.impl.SessionFactoryImpl;
     8 import org.junit.Test;
     9 
    10 import com.itheima09.hibernate.domain.Person;
    11 import com.itheima09.hibernate.utils.HibernateUtils;
    12 
    13 public class PersonDao extends HibernateUtils{
    14     @Test
    15     public void savePerson(){
    16         //创建配置文件对象 
    17         Configuration configuration = new Configuration();
    18         //加载配置文件   1、该配置文件必须放在根目录下  2、名称必须为hibernate.cfg.xml
    19         configuration.configure();
    20         //有一个参数,该参数为hibernate配置文件的路径
    21         //configuration.configure("");
    22         //创建sessionFactory
    23         SessionFactory sessionFactory = configuration.buildSessionFactory();
    24         //打开一个session
    25         Session session = sessionFactory.openSession();
    26         //创建一个事务
    27         Transaction transaction = session.beginTransaction();
    28         Person person = new Person("");
    29         person.setName("王二麻子");
    30         person.setDescription("霸气");
    31         //利用session把person对象保存
    32         session.save(person);
    33         //事务提交
    34         transaction.commit();
    35         //session关闭
    36         session.close();
    37     }
    38     
    39     @Test
    40     public void updatePerson(){
    41         //加载配置文件
    42         Configuration configuration = new Configuration();
    43         configuration.configure();
    44         SessionFactory factory = configuration.buildSessionFactory();
    45         Session session = factory.openSession();
    46         Transaction transaction = session.beginTransaction();
    47         /**
    48          * 根据主键查询数据库表中的一行记录
    49          * 第一个参数为持久化类的class形式
    50          * 第二个参数为对象的序列化,能接受基本类型的包装类、String
    51          */
    52         Person person = (Person)session.get(Person.class, 1L);
    53         person.setDescription("就是牛");
    54         session.update(person);
    55         transaction.commit();//事务的提交
    56         session.close();
    57     }
    58     
    59     @Test
    60     public void testQueryPerson(){
    61         Session session = sessionFactory.openSession();
    62         //from后面跟的是持久化类名,不是表名
    63         List<Person> personList = session.createQuery("from Person").list();
    64         System.out.println(personList.size());
    65     }
    66     
    67     @Test
    68     public void testDeletePerson(){
    69         /**
    70          * 1、从数据库中把pid为1的数据提取出来
    71          * 2、删除
    72          */
    73         Session session = sessionFactory.openSession();
    74         Transaction transaction = session.beginTransaction();
    75         //把pid为1的持久化对象提取出来
    76         Person person = (Person)session.get(Person.class,1L);
    77         session.delete(person);
    78         transaction.commit();
    79         session.close();
    80     }
    81     
    82     @Test
    83     public void testSessionFactory(){
    84         
    85     }
    86 }
    Dao.java

    Hibernate的流程

    说明:

    1、  crud操作是由session来完成的

    2、  在hibernate中事务不是自动提交的

    入门例子详细解析

    Configuration类

         利用该类加载了hibernate的配置文件

    sessionFactory类

    1、  hibernate配置文件的信息、持久化类的信息、映射文件的信息全部在该类中

    2、  sessionFactory对象有且只有一个

    3、  生命周期是整个hibernate实例

    4、  sessionFactory本身就是线程安全的

    5、  二级缓存在sessionFactory中存放

    6、  sessionFactory和数据库的链接没有直接的关系

    session类

    1、  crud操作由session来完成的

    2、  一个session代表数据库的一个链接

    内部执行流程

     

    Hibernate的反向工程

     工具数据库表生成Hibernate工程(简单粗暴)

    第一步

    第二步

    第三步

     

    第四步

     

    以上四步就是一个工程变成hibernate工程

    第五步

     

    该模式是myeclipse链接数据库的模式

    第六步

     

    第七步

     

    在该模式下创建了一个链接

    第八步

     

    第九步

     

    第十步

          

    第十一步

     

    第十二步

           上述的步骤完成以后,会看到如下的结构:

     

    Hibernate中的类型

     在hibernate中有两种类型:java type,hibernate type

     Java type

      Hibernate内部直接提供了java类型到数据库的对照表

    说明:用java类型可以直接完成从java类型到数据库类型的映射

     

    Hibernate类型

           从上面可以看出如果选择hibernate类型,需要查找该hibernate类型对应的java类型,从而再找到数据库类型,所以java类型效率比较高

    主键的产生器

    Increment:
        

                  查找主键的最大值,在最大值的基础上加1

                  效率比较低

    Assigned

           注意:由程序手动赋值

    Identity

           支持主键自动增长

    Uuid

     

           持久化类中的属性必须是String类型

    Native

           Hibernate会根据数据库的不同,选择合适的主键的生成策略

    Sequence

            是oracle内部特有的内容,相当于uuid,所以是字符串类型

    对象的状态

    应用场景

           如果一个班的所有的学生要把考试的成绩同步到数据库的表中,如果每一个学生和数据库交互一次,那么如果有60个学生,需要跟数据库交互60次,这样效率比较低

    对象的状态的值

           1.临时状态

           2.持久化状态

           3.脱管状态

    案例1

     

     说明:

    1.临时状态:

    1、  把16,17,18这三行代码的对象的状态称为临时对象,其特征是该对象与hibernate没有关系。(没有和hibernate联系)

    2.持久化状态

    2、  当执行19行代码的时候,person对象由临时状态转化成持久化状态,这个时候数据库没有对应的数据,但是该对象在hibernate内部

    3、  当执行20行代码的时候,事务提交了,该对象还是持久化状态的对象,数据库中有对应的值了

     2.脱管状态

    4、  当执行完21行代码的时候,session关闭了,该对象成为脱管状态的对象(session关闭)

    案例2

     

    说明:

    1、  session.get方法提取出来的是一个持久化状态的对象

    2、  当事务提交的时候,hibernate内部自动更新

    案例3

     

    案例4

    案例5

     

    说明:

         该例子对象的状态由持久化----->脱管----->持久化

            当事务提交的时候,hibernate内部只管持久化状态的对象,对于临时状态和脱管状态是不管的。

    案例6

      说明:

          利用session.clear方法把hibernate中所有的持久化状态转化为脱管状态。

    案例7

    说明:

         Person对象对于第一个session而言,当session还没有关闭的时候,是持久化对象

         Person对象对于第二个session而言,该对象和该session没有交互,所以一个对象是一个持久化状态的对象是针对session而言的

    对象转化图

     

    总结

    可以通过session.get,save,update,方法把一个对象变成持久化状态的对象
    
    可以通过session.close   session.evict   session.clear方法把一个对象变成脱管状态的对象

    Hibernate的一级缓存

    缓存

    数据缓存

    Map<String,Object>

    String是缓存中数据的唯一标示

    Object是key所对应的值

    对象缓存

     

    说明:

    1、  对象缓存是一个集合(List),而不是一个map
    
    2、  每一个对象中都有一个唯一的标示符
    
    3、  在hibernate中,该标示符为主键

    缓存研究内容

           缓存的生命周期:

             把一个对象放入到缓存中

             把一个对象从缓存中提取出来

             把一个对象从缓存中清除

        把一些对象从缓存中清除

        把缓存中的数据同步到数据库中

        把数据库中的数据同步到缓存中

    一级缓存

    说明:

           一级缓存是session缓存

           当session开启的时候,一级缓存起作用,当session关闭的时候,一级缓存销毁了

           Session的缓存存放的是私有数据

    操作:

    把一个对象放入到一级缓存中

    A:
    Get方法

     

    说明:

         Session.get方法把一个对象放入到了一级缓存中

    B:
    Statictis方法:统计方法

     

    说明在session的一级缓存中存放了两个对象

    c:
    Save方法:

     

    说明:session.save方法把对象放入到一级缓存中了

    把一个对象从一级缓存中清除:

    Evict方法:

     

    Clear方法:

     

    Close方法:

           当执行session.close方法的时候,一级缓存的生命周期结束了

    把数据库的数据同步到缓存中:

    Refresh方法:

     

    把缓存中的数据同步到数据库中:

    Flush方法:

     

    说明:

     当执行94行代码的时候,hibernate会检查一级缓存中所有的持久化状态的对象,

    如果该持久化状态的对象没有标示符的值,则会发出insert语句,如果该持久化状态的对象有标示符的值,则会对照副本,看是否和副本一致,如果一致,则什么都不做,如果不一致,则发出update语句。

    总结

           一级缓存提供了一个临时存放对象的一个内存结构,当hibernate对对象进行操作的时候,仅仅改变的是对象的属性,改变的是一级缓存中的对象的属性,在session.flush之前的代码可以任意写,因为这个时候,并没有和数据库交互。当执行session.flush的时候,hibernate会检查一级缓存中的对象的情况,发出insert或者update语句。

    基础部分的重点

    1、  很熟练掌握内部执行流程

    2、  错误分析的熟练掌握

    Session的产生方式

    sessionFactory.openSession方法

          

       每一次执行openSession的时候都会新打开一个session

    sessionFactory.getCurrentSession方法

    原理

    1、  从当前线程中(ThreadLocal)中,把session提取出来

    2、  如果第一步失败,则调用openSession方法创建一个session

    3、  接着第二步,把session放入到threadlocal中

    4、  走第一步

    好处

           不管有几个类完全松耦合,如果这几个类要用到同一个session,在运行的时候,如果这几个类在同一个线程下运行,利用threadlocal就能够保证是同一个session。

    步骤

    1、  在hibernate.cfg.xml文件中

     

    2、  在客户端

     

    说明:

    1、  crud操作必须在事务的环境下运行

    2、  事务提交,session自动关闭。

    3、  这种方式强制把事务和session绑定在一起了。

     1 import org.hibernate.Session;
     2 import org.hibernate.Transaction;
     3 import org.junit.Test;
     4 
     5 import com.itheima09.hibernate.domain.Account;
     6 import com.itheima09.hibernate.utils.HibernateUtils;
     7 
     8 public class SessionCreateMethod extends HibernateUtils{
     9     @Test
    10     public void testGetCurrentSession(){
    11         Session session = sessionFactory.getCurrentSession();
    12         Transaction transaction = session.beginTransaction();
    13         Account account = (Account)session.get(Account.class, 1L);
    14         transaction.commit();
    15         System.out.println(session.isOpen());
    16     }
    17 }
    SessionCreateMethod.java

    关系操作

    一对多的单项

    持久化类和映射文件:

          

           可以看到只能通过Classes查找到Student,但是不能通过student查找到Classes。

     

       从映射文件可以看出,set元素描述了两个方面的内容:

    1、  key从外键的角度描述了两者之间的关系,用于生成sql语句

    2、  one-to-many从类与类的角度描述了两者的关系,用于客户端的编码

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Classes">
     6         <id name="cid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="100"></property>
    11         <!-- 
    12             cascade 级联
    13                save-update
    14                       当保存或者更新classes的时候,级联操作student
    15          -->
    16         <set name="students" cascade="save-update">
    17             <!-- 
    18                 key代表外键
    19                 用来关联classes表和student表,用于在hibernate低层生成sql语句
    20              -->
    21             <key>
    22                 <column name="cid"></column>
    23             </key>
    24             <!-- 
    25                 建立类与类之间的关联,用于客户端的编码
    26              -->
    27             <one-to-many class="com.itheima09.hibernate.domain.Student"/>
    28         </set>
    29     </class>
    30 </hibernate-mapping>
    Classes.hbm.xml
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Student">
     6         <id name="sid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="100"></property>
    11     </class>
    12 </hibernate-mapping>
    Student.hbm.xml

    操作

    保存班级:

          

    保存学生

          

    保存班级同时保存学生

          

    这种做法不好,因为在客户端需要操作session.save这个代码很多次。

    级联操作

    保存班级级联保存学生

    1、  在映射文件中

     

    2、  在代码中

     

     说明:

    1、  在hibernate中,通过session.save方法保存一个持久化对象这种方式称为显示保存。

    2、  在hibernate中,通过级联的方式来操作一个对象,这样的方式称为隐式操作。

    3、  对student对象进行了隐式的保存操作,是因为student是一个临时状态的对象,在数据库中没有对应的记录,所以应该对student执行insert语句

    更新班级级联更新学生

          

           说明:

    1、  当执行108行的时候,产生了如下的sql语句

     

    2、  在执行110行代码的时候,产生了如下的sql语句

     

    3、  执行114行代码的时候,产生了如下的sql语句

     

    该update语句产生了3条,因为该班级中有3个学生,3个学生的属性同时发生改变。
    4、没有发出更新classes的update语句,因为classes的属性没有发生改变。

      1 import java.util.HashSet;
      2 import java.util.Set;
      3 
      4 import org.hibernate.Session;
      5 import org.hibernate.Transaction;
      6 import org.junit.Test;
      7 
      8 import com.itheima09.hibernate.domain.Classes;
      9 import com.itheima09.hibernate.domain.Student;
     10 import com.itheima09.hibernate.utils.HibernateUtils;
     11 
     12 /**
     13  * 1、保存班级
     14  * 2、保存学生
     15  * 3、保存班级的同时保存学生
     16  * 4、更新班级
     17  * 5、更新学生
     18  * 6、已经存在一个班级,新建一个学生,让该学生加入到该班级
     19  * 7、已经存在两个班级,已经存在一个学生,让一个学生从一个班级转移到另外一个班级
     20  * 8、已经存在一个班级,已经存在一个学生,解除该学生和该班级之间的关系
     21  * 9、解除该班级和所有的学生之间的关系
     22  * 10、删除学生
     23  * 11、删除班级
     24  * @author zd
     25  *
     26  */
     27 public class OneToManySingleTest extends HibernateUtils{
     28     //1、保存班级
     29     @Test
     30     public void testSaveClasses(){
     31         Session session = sessionFactory.getCurrentSession();
     32         Transaction transaction = session.beginTransaction();
     33         Classes classes = new Classes();
     34         classes.setName("云9");
     35         classes.setDescription("是一个神奇的班级");
     36         session.save(classes);
     37         transaction.commit();
     38     }
     39     // 2、保存学生
     40     @Test
     41     public void testSaveStudent(){
     42         Session session = sessionFactory.getCurrentSession();
     43         Transaction transaction = session.beginTransaction();
     44         Student student = new Student();
     45         student.setName("带头大哥:班长");
     46         student.setDescription("厉害");
     47         session.save(student);
     48         transaction.commit();
     49     }
     50     //3、保存班级的同时保存学生
     51     @Test
     52     public void testSaveClassesAndStudent(){
     53         Session session = sessionFactory.getCurrentSession();
     54         Transaction transaction = session.beginTransaction();
     55         
     56         Classes classes = new Classes();
     57         classes.setName("java基础班");
     58         classes.setDescription("信老毕,有肉吃");
     59         
     60         Student student1 = new Student();
     61         student1.setName("王二麻子");
     62         student1.setDescription("很酷");
     63         
     64         Student student2 = new Student();
     65         student2.setName("上面的哥");
     66         student2.setDescription("脸上麻子比较多");
     67         
     68         session.save(classes);
     69         session.save(student1);
     70         session.save(student2);
     71         transaction.commit();
     72     }
     73     
     74     @Test
     75     public void testSaveClasses_Cascade_SaveStudent(){
     76         Session session = sessionFactory.getCurrentSession();
     77         Transaction transaction = session.beginTransaction();
     78         
     79         Classes classes = new Classes();
     80         classes.setName("java基础班");
     81         classes.setDescription("信老毕,有肉吃");
     82         
     83         Set<Student> students = new HashSet<Student>();
     84         Student student1 = new Student();
     85         student1.setName("王二麻子");
     86         student1.setDescription("很酷");
     87         Student student2 = new Student();
     88         student2.setName("上面的哥");
     89         student2.setDescription("脸上麻子比较多");
     90         students.add(student1);
     91         students.add(student2);
     92         //通过classe建立classes与student之间的关联
     93         classes.setStudents(students);
     94         session.save(classes);
     95         transaction.commit();
     96     }
     97     
     98     /**
     99      * 获取cid为3的班级,再获取该班级的所有的学生,并且变化其属性
    100      */
    101     @Test
    102     public void testUpdateClasses_Cascade_UpdateStudent(){
    103         Session session = sessionFactory.getCurrentSession();
    104         Transaction transaction = session.beginTransaction();
    105         //获取cid为3的classes
    106         Classes classes = (Classes)session.get(Classes.class, 3L);
    107         //获取该班级所有的学生
    108         Set<Student> students = classes.getStudents();
    109         for(Student student:students){
    110             student.setDescription("aaa");
    111         }
    112         transaction.commit();
    113     }
    114 }
    TestOneToMany.java

    再次讨论session.flush:

    1、  检查session一级缓存中所有的持久化对象的状态,决定发出insert语句或者update语句。

    2、  会检查所有的持久化对象的关联对象,如果有级联操作,则对关联对象进行insert语句或者update语句。

    关系操作

    让一个新的学生加入到已经存在的班级

          

    说明:

    1、  当执行127行代码的时候,发出了加载classes的sql语句

    2、  当执行129行代码的时候,发出了加载classes班级中的所有的学生的sql语句

    3、  因为在Classes.hbm.xml文件中set元素的cascade属性设置了save-update,所以在更新classes的时候,要检查classes中的students集合,发现集合中多了一个对象,所以要对该对象(student)执行insert语句。

    4、  当执行session.flush的时候,会发出维护关系的update语句,因为classes负责维护classes与student之间的关系。

     

    重新建立关系1:

    说明:

    1、  执行141行的时候,发出加载student的sql语句

    2、  执行143行的时候,发出加载cid为1的班级的sql语句

    3、  执行144行的时候,发出加载cid为2的班级的sql语句

    4、  执行146行的时候,发出维护关系的sql语句

     

    因为解除关系了,所以cid为null

    5、  执行148行的时候,

     

    因为建立关系了,所以更新了外键。

    分析:从上面的代码和sql语句可以看出,外键变了两次,但是不需要改变两次。

    重新建立关系2:

       说明:只需要建立关系就可以了,因为发出的是更新外键的sql语句。把外键的值改变了就可以了。

    解除一个学生和一个班级之间的关系

      

    解除该班级和所有的学生之间的关系

      

    说明:当执行classes.setStudents(null)的时候,不需要根据班级加载学生,所以这样做效率比较高。

    删除班级

    说明

    1、  classes负责维护关系

    2、  在执行session.flush的时候,在删除班级之前,解除该班级和所有的学生之间的关系

    3、  解除关系以后,再删除班级

    4、  先查询班级,再查询该班级中的每一个学生,再根据每一个学生的sid删除每一个学生,这样效率比较低

    删除班级级联删除学生

     

    Cascade与inverse的区别

    1、  cascade描述的是对象与对象之间的关系

    cascade和外键没有关系,在student表中,sid、name、description和cascade有关系,但是cid和cascade没有关系。

    2、  inverse描述的是对象与外键之间的关系

    inverse只和cid有关系,如果维护,则发出update语句(更新外键的sql语句),如果不维护,则不管。

    总结

    1、  只能通过classes操作student
    
    2、  只要classes维护关系,就会发出维护关系的update语句,所以让classes维护关系效率比较低
    
    3、  让student维护关系效率比较高
    
    4、  Session.flush的时候,hibernate内部做的事情
    
    1、  检查一级缓存中所有的持久化对象,决定发出insert语句还是update语句
    
    2、  检查持久化对象的关联对象,看持久化对象的映射文件中的cascade,决定关联对象是否发出insert语句或者update语句或者delete语句
    
    3、  检查持久化对象的映射文件的针对关联对象的inverse属性,来决定是否维护关系。如果维护关系,则发出update语句(维护关系的语句)

    一对多的双向

    持久化类和映射文件

     

     

    操作

    保存学生级联保存班级

     

    说明:

         1、36行代码是通过student建立student与classes之间的关联,所以看student.hbm.xml文件

            2、在Student.hbm.xml文件中,设置了针对classes的级联

                 

            3、在保存学生的时候级联保存了班级

            4、保存学生相当于维护了关系

              

                  在保存学生的时候,cid有值了,不需要发出维护关系的update语句。

    新建一个学生,并且和一个已经的班级关联:

    学生转班:

       

    说明:从上述的sql语句可以看出不仅更新了外键,而且把其他属性也更新了,所以更新关系指的就是更新student对象本身的操作。

    解除一个班级和一个学生之间的关系:

      

    解除该班级和所有的学生的关系:

     

    这样做是通过学生解除学生和班级之间的关系,但是效率不高

    总结

        一般情况下,一对多,多的一方维护关系效率要比较高。

     1 import java.io.Serializable;
     2 import java.util.Set;
     3 
     4 public class Classes implements Serializable{
     5     private Long cid;
     6     private String name;
     7     private String description;
     8     private Set<Student> students;
     9     public Long getCid() {
    10         return cid;
    11     }
    12     public void setCid(Long cid) {
    13         this.cid = cid;
    14     }
    15     public String getName() {
    16         return name;
    17     }
    18     public void setName(String name) {
    19         this.name = name;
    20     }
    21     public String getDescription() {
    22         return description;
    23     }
    24     public void setDescription(String description) {
    25         this.description = description;
    26     }
    27     public Set<Student> getStudents() {
    28         return students;
    29     }
    30     public void setStudents(Set<Student> students) {
    31         this.students = students;
    32     }
    33 }
    Classes.java
     1 import java.io.Serializable;
     2 
     3 public class Student implements Serializable{
     4     private Long sid;
     5     private String name;
     6     private String description;
     7     private Classes classes;
     8     
     9     public Classes getClasses() {
    10         return classes;
    11     }
    12     public void setClasses(Classes classes) {
    13         this.classes = classes;
    14     }
    15     public Long getSid() {
    16         return sid;
    17     }
    18     public void setSid(Long sid) {
    19         this.sid = sid;
    20     }
    21     public String getName() {
    22         return name;
    23     }
    24     public void setName(String name) {
    25         this.name = name;
    26     }
    27     public String getDescription() {
    28         return description;
    29     }
    30     public void setDescription(String description) {
    31         this.description = description;
    32     }
    33 }
    Student.java
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Student">
     6         <id name="sid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="100"></property>
    11         <!-- 
    12             column 为外键
    13          -->
    14         <many-to-one name="classes" column="cid" 
    15             class="com.itheima09.hibernate.domain.Classes" cascade="save-update">
    16         </many-to-one>
    17     </class>
    18 </hibernate-mapping>
    Student.hbm.xml
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Classes">
     6         <id name="cid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="100"></property>
    11         <!-- 
    12             cascade 级联
    13                save-update
    14                       当保存或者更新classes的时候,级联操作student
    15             inverse  维护关系
    16                 true    不维护关系
    17                 false   维护关系
    18                 default  false
    19          -->
    20         <set name="students" cascade="all">
    21             <!-- 
    22                 key代表外键
    23                 用来关联classes表和student表,用于在hibernate低层生成sql语句
    24              -->
    25             <key>
    26                 <column name="cid"></column>
    27             </key>
    28             <!-- 
    29                 建立类与类之间的关联,用于客户端的编码
    30              -->
    31             <one-to-many class="com.itheima09.hibernate.domain.Student"/>
    32         </set>
    33     </class>
    34 </hibernate-mapping>
    Classes.hbm.xml
      1 import java.util.Set;
      2 
      3 import javax.annotation.Generated;
      4 
      5 import org.hibernate.Session;
      6 import org.hibernate.Transaction;
      7 import org.junit.Test;
      8 
      9 import com.itheima09.hibernate.domain.Classes;
     10 import com.itheima09.hibernate.domain.Student;
     11 import com.itheima09.hibernate.utils.HibernateUtils;
     12 
     13 /**
     14  * 1、保存班级
     15  * 2、保存学生
     16  * 3、保存班级的同时保存学生
     17  * 4、更新班级
     18  * 5、更新学生
     19  * 6、已经存在一个班级,新建一个学生,让该学生加入到该班级
     20  * 7、已经存在两个班级,已经存在一个学生,让一个学生从一个班级转移到另外一个班级
     21  * 8、已经存在一个班级,已经存在一个学生,解除该学生和该班级之间的关系
     22  * 9、解除该班级和所有的学生之间的关系
     23  * 10、删除学生
     24  * 11、删除班级
     25  * @author zd
     26  *
     27  */
     28 public class OneToManyTest extends HibernateUtils{
     29     @Test
     30     public void testSaveStudent_Cascade_SaveClasses(){
     31         Session session = sessionFactory.getCurrentSession();
     32         Transaction transaction = session.beginTransaction();
     33         Student student = new Student();
     34         student.setName("c罗");
     35         Classes classes = new Classes();
     36         classes.setName("皇马");
     37         //通过student建立student与classes之间的关联
     38         student.setClasses(classes);
     39         session.save(student);
     40         transaction.commit();
     41     }
     42     
     43     /**
     44      * 已经存在一个班级,新建一个学生,让该学生加入到该班级
     45      */
     46     @Test
     47     public void testSaveStudent_BuildR(){
     48         Session session = sessionFactory.getCurrentSession();
     49         Transaction transaction = session.beginTransaction();
     50         //把 cid为4的班级提取出来
     51         Classes classes = (Classes)session.get(Classes.class, 4L);
     52         Student student = new Student();
     53         student.setName("梅西");
     54         //通过student建立关联
     55         student.setClasses(classes);
     56         session.save(student);
     57         transaction.commit();
     58     }
     59     /**
     60      * 一个学生从一个班级转移到另外一个班级
     61      * sid为8的学生从cid为2的班级转移到cid为1的班级
     62      */
     63     @Test
     64     public void testTransform(){
     65         Session session = sessionFactory.getCurrentSession();
     66         Transaction transaction = session.beginTransaction();
     67         Student student = (Student)session.get(Student.class, 8L);
     68         Classes classes  =(Classes)session.get(Classes.class, 1L);
     69         //student有一个新的班级
     70         student.setClasses(classes);
     71         transaction.commit();
     72     }    
     73     
     74     /**
     75      * 解除一个学生和一个班级之间的关系
     76      */
     77     @Test
     78     public void testReleaseR(){
     79         Session session = sessionFactory.getCurrentSession();
     80         Transaction transaction = session.beginTransaction();
     81         Student student = (Student)session.get(Student.class, 9L);
     82         student.setClasses(null);
     83         transaction.commit();
     84     }
     85     
     86     /**
     87      * 解除该班级和所有的学生之间的关系
     88      */
     89     @Test
     90     public void testReleaseAll(){
     91         Session session = sessionFactory.getCurrentSession();
     92         Transaction transaction = session.beginTransaction();
     93         Classes classes = (Classes)session.get(Classes.class, 1L);
     94         Set<Student> students = classes.getStudents();
     95         for(Student student:students){
     96             student.setClasses(null);
     97         }
     98         transaction.commit();
     99     }
    100 }
    OneToManyTest.java

    多对多的双向

    持久化和映射文件:

     

    关系的维护:

    1、  建立关系,相当于在第三张表中插入一行数据

    2、  解除关系,相当于在第三张表中删除一行数据

    3、  重新建立关系,相当于先删除一行数据,再增加一行数据

    4、  多对多,谁维护关系效率都一样

    操作:

    让一个新的学生和一个已经存在的课程发生关联:

          

    说明:

    1、65行代码是通过课程建立课程与学生之间的关联,course.getStudents()的时候会发出根据课程查找该学生的sql语句,这样做效率比较低

    解除一个学生和一门课程之间的关系

          

    解除该课程和所有的学生之间的关联:

     

    一个学生从一门课程转移到另外一门课程:

          

     1 <?xml version='1.0' encoding='utf-8'?>
     2 <!DOCTYPE hibernate-configuration PUBLIC
     3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
     4         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
     5 <hibernate-configuration>
     6     <!-- 
     7         一个session-factory代表一个数据库
     8      -->
     9 <session-factory>
    10     <!-- 
    11         链接数据库的用户名
    12     -->
    13     <property name="connection.username">root</property>
    14     <!-- 
    15         链接数据库的密码
    16     -->
    17     <property name="connection.password">root</property>
    18     <!-- 
    19         链接数据库的驱动
    20     -->
    21     <property name="connection.driver_class">
    22         com.mysql.jdbc.Driver
    23     </property>
    24     <!-- 
    25         链接数据库的url
    26     -->
    27     <property name="connection.url">
    28         jdbc:mysql://localhost:3306/itheima09_hibernate
    29     </property>
    30     <!-- 
    31         方言
    32         告诉hibernate用什么样的数据库
    33     -->
    34     <property name="dialect">
    35         org.hibernate.dialect.MySQLDialect
    36     </property>
    37     <!-- 
    38         validate 加载hibernate时,验证数据库的结构
    39         update  加载hibernate时,检查数据库,如果表不存在,则创建,如果存在,则更新
    40         create  每次加载hiberante,都会创建表
    41         create-drop  每次加载hiberante,创建,卸载hiberante时,销毁
    42     -->
    43     <property name="hbm2ddl.auto">update</property>
    44     <!-- 
    45         显示sql语句
    46     -->
    47     <property name="show_sql">true</property>
    48     <!-- 
    49         格式化sql语句
    50     -->
    51     <property name="format_sql">true</property>
    52     <!-- 
    53         session要从当前线程中产生
    54     -->
    55     <property name="current_session_context_class">thread</property>
    56     <!-- 
    57         加载映射文件
    58     -->
    59     <mapping resource="com/itheima09/hibernate/domain/Course.hbm.xml" />
    60     <mapping resource="com/itheima09/hibernate/domain/Student.hbm.xml" />
    61 </session-factory>
    62 </hibernate-configuration>
    hibernate.cfg.xml
     1 import java.io.Serializable;
     2 import java.util.Set;
     3 
     4 public class Course implements Serializable{
     5     private Long cid;
     6     private String name;
     7     private String description;
     8     private Set<Student> students;
     9     public Long getCid() {
    10         return cid;
    11     }
    12     public void setCid(Long cid) {
    13         this.cid = cid;
    14     }
    15     public String getName() {
    16         return name;
    17     }
    18     public void setName(String name) {
    19         this.name = name;
    20     }
    21     public String getDescription() {
    22         return description;
    23     }
    24     public void setDescription(String description) {
    25         this.description = description;
    26     }
    27     public Set<Student> getStudents() {
    28         return students;
    29     }
    30     public void setStudents(Set<Student> students) {
    31         this.students = students;
    32     }
    33 }
    Course.java
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Course">
     6         <id name="cid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="50"></property>
    11         <set name="students" table="student_course" cascade="save-update">
    12             <key>
    13                 <column name="cid"></column>
    14             </key>
    15             <many-to-many class="com.itheima09.hibernate.domain.Student" 
    16             column="sid"></many-to-many>
    17         </set>
    18     </class>
    19 </hibernate-mapping>
    Course.hbm.xml
     1 package com.itheima09.hibernate.domain;
     2 
     3 import java.io.Serializable;
     4 import java.util.Set;
     5 
     6 public class Student implements Serializable{
     7     private Long sid;
     8     private String name;
     9     private String description;
    10     private Set<Course> courses;
    11     public Long getSid() {
    12         return sid;
    13     }
    14     public void setSid(Long sid) {
    15         this.sid = sid;
    16     }
    17     public String getName() {
    18         return name;
    19     }
    20     public void setName(String name) {
    21         this.name = name;
    22     }
    23     public String getDescription() {
    24         return description;
    25     }
    26     public void setDescription(String description) {
    27         this.description = description;
    28     }
    29     public Set<Course> getCourses() {
    30         return courses;
    31     }
    32     public void setCourses(Set<Course> courses) {
    33         this.courses = courses;
    34     }
    35 }
    Student.java
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Student">
     6         <id name="sid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="50"></property>
    11         <!-- 
    12             table为关联表
    13                    为了生成关联的sql语句
    14          -->
    15         <set name="courses" table="student_course" cascade="save-update">
    16             <!-- 
    17                 外键
    18              -->
    19             <key>
    20                 <column name="sid"></column>
    21             </key>
    22             <many-to-many class="com.itheima09.hibernate.domain.Course" 
    23                 column="cid"></many-to-many>
    24         </set>
    25     </class>
    26 </hibernate-mapping>
    Student.hbm.xml
      1 import java.util.HashSet;
      2 import java.util.Set;
      3 
      4 import org.hibernate.Session;
      5 import org.hibernate.Transaction;
      6 import org.junit.Test;
      7 
      8 import com.itheima09.hibernate.domain.Course;
      9 import com.itheima09.hibernate.domain.Student;
     10 import com.itheima09.hibernate.utils.HibernateUtils;
     11 
     12 /**
     13  * 1、保存课程,同时保存学生(级联)
     14  * 2、更新课程,同时更新学生(级联)
     15  * 3、已经存在一门课程,新建一个学生,让该学生加入到该课程
     16  * 4、已经存在一个学生,新建一门课程,让该学生加入到该课程
     17  * 5、解除一门课程和一个学生之间的关系
     18  * 6、解除一门课程和这门课程所有的学生之间的关系
     19  * 7、删除课程
     20  * 8、删除学生
     21  * 9、一个学生从一门课程转移到另外一个门课程
     22  * @author zd
     23  *
     24  */
     25 public class ManyToManyTest extends HibernateUtils{
     26     @Test
     27     public void testCreateTable(){
     28         
     29     }
     30     
     31     /**
     32      * 保存课程,同时保存学生
     33      */
     34     @Test
     35     public void testSaveStudent_Cascade_SaveCourse(){
     36         Session session = sessionFactory.getCurrentSession();
     37         Transaction transaction = session.beginTransaction();
     38         Student student = new Student();
     39         student.setName("aaa");
     40         Course course = new Course();
     41         course.setName("java基础");
     42         //通过保存学生级联保存课程
     43         Set<Course> courses = new HashSet<Course>();
     44         courses.add(course);
     45         //建立了学生和课程之间的关系
     46         student.setCourses(courses);
     47         session.save(student);
     48         transaction.commit();
     49     }
     50     
     51     /**
     52      * 已经存在一门课程,新建一个学生,让该学生加入到该课程
     53      */
     54     @Test
     55     public void testSaveStudent_BuildR(){
     56         Session session = sessionFactory.getCurrentSession();
     57         Transaction transaction = session.beginTransaction();
     58         //得到cid为1的课程
     59         Course course = (Course)session.get(Course.class, 1L);
     60         //新建一个学生
     61         Student student = new Student();
     62         student.setName("aaa");
     63         //建立该课程和该学生之间的关联
     64         //course.getStudents().add(student);  //通过课程关联学生  根据课程查找学生要发出sql语句
     65         Set<Course> courses = new HashSet<Course>();
     66         courses.add(course);
     67         student.setCourses(courses); //通过学生建立学生和课程之间的关联
     68         session.save(student);
     69         transaction.commit();
     70     }
     71     
     72     /**
     73      * 解除一门课程和一个学生之间的关系
     74      */
     75     @Test
     76     public void testReleaseR(){
     77         /**
     78          * 解除cid为1的课程和sid为1的学生之间的关系
     79          */
     80         Session session = sessionFactory.getCurrentSession();
     81         Transaction transaction = session.beginTransaction();
     82         Course course = (Course)session.get(Course.class, 1L);
     83         Student student = (Student)session.get(Student.class, 1L);
     84         course.getStudents().remove(student);//通过course解除关系
     85         //student.getCourses().remove(course);//通过student解除关系
     86         transaction.commit();
     87     }
     88     
     89     /**
     90      * 解除一门课程和这门课程所有的学生之间的关系
     91      */
     92     @Test
     93     public void testReleaseAllR(){
     94         Session session = sessionFactory.getCurrentSession();
     95         Transaction transaction = session.beginTransaction();
     96         /**
     97          * 解除cid为1的课程和该课程所有的学生之间的关系
     98          */
     99         Course course = (Course)session.get(Course.class, 1L);
    100         course.setStudents(null);
    101         transaction.commit();
    102     }
    103     
    104     /**
    105      * 一个学生从一门课程转移到另外一个门课程
    106      *  把sid为1的学生从cid为1的课程转移到cid为2的课程
    107      */
    108     @Test
    109     public void testTransform(){
    110         Session session = sessionFactory.getCurrentSession();
    111         Transaction transaction = session.beginTransaction();
    112         //以学生维护关系
    113         Student student = (Student)session.get(Student.class, 1L);
    114         Course course1  =(Course)session.get(Course.class, 1L);
    115         Course course2 = (Course)session.get(Course.class, 2L);
    116         student.getCourses().remove(course1);//移除
    117         student.getCourses().add(course2);//增加
    118         transaction.commit();
    119     }
    120 }
    ManyToManyTest.java
     1 import org.hibernate.SessionFactory;
     2 import org.hibernate.cfg.Configuration;
     3 
     4 public class HibernateUtils {
     5     public static SessionFactory sessionFactory;
     6     static{
     7         Configuration configuration = new Configuration();
     8         configuration.configure();
     9         sessionFactory = configuration.buildSessionFactory();
    10     }
    11 }
    HibernateUtils.java

    一对一的双向

          

    所以上面的代码是不对的,因为上面的代码会导致student2和student1的外键都为6L。

    总结

    1、  关系的角度
    
    一对多反映的是类与集合的关系
    
    多对一反映的是类与类之间的关系
    
    多对多反映的是类与集合之间的关系
    
    2、  一对多,多的一方维护关系,效率比较高
    
    3、  多对多,谁维护效率都一样
    
    4、  通过谁建立关系,看谁的映射文件
    
    5、  Cascade与inverse之间的区别

    性能分析

    抓取策略

    研究对象

           研究怎么样提取集合的,该策略应该作用与set元素上

    研究从一的一方加载多的一方

    案例

    查询cid为1的班级的所有的学生

       

    说明:通过一条sql语句:左外链接,把classes与student表的数据全部提取出来。

    如果是如下的策略:

     

    先查询classes,再次查询student

     

    先查询classes,再次查询student。

    查询所有的班级的所有的学生

          

      该需求翻译过来含有子查询

          

       如果含有子查询,必须用subselect

           改进:

    查询班级为1,2,3,4的所有的学生

          

     1 import org.hibernate.SessionFactory;
     2 import org.hibernate.cfg.Configuration;
     3 
     4 public class HibernateUtils {
     5     public static SessionFactory sessionFactory;
     6     static{
     7         Configuration configuration = new Configuration();
     8         configuration.configure();
     9         sessionFactory = configuration.buildSessionFactory();
    10     }
    11 }
    HibernateUtils.java
     1 <?xml version='1.0' encoding='utf-8'?>
     2 <!DOCTYPE hibernate-configuration PUBLIC
     3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
     4         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
     5 <hibernate-configuration>
     6     <!-- 
     7         一个session-factory代表一个数据库
     8      -->
     9 <session-factory>
    10     <!-- 
    11         链接数据库的用户名
    12     -->
    13     <property name="connection.username">root</property>
    14     <!-- 
    15         链接数据库的密码
    16     -->
    17     <property name="connection.password">root</property>
    18     <!-- 
    19         链接数据库的驱动
    20     -->
    21     <property name="connection.driver_class">
    22         com.mysql.jdbc.Driver
    23     </property>
    24     <!-- 
    25         链接数据库的url
    26     -->
    27     <property name="connection.url">
    28         jdbc:mysql://localhost:3306/itheima09_hibernate
    29     </property>
    30     <!-- 
    31         方言
    32         告诉hibernate用什么样的数据库
    33     -->
    34     <property name="dialect">
    35         org.hibernate.dialect.MySQLDialect
    36     </property>
    37     <!-- 
    38         validate 加载hibernate时,验证数据库的结构
    39         update  加载hibernate时,检查数据库,如果表不存在,则创建,如果存在,则更新
    40         create  每次加载hiberante,都会创建表
    41         create-drop  每次加载hiberante,创建,卸载hiberante时,销毁
    42     -->
    43     <property name="hbm2ddl.auto">update</property>
    44     <!-- 
    45         显示sql语句
    46     -->
    47     <property name="show_sql">true</property>
    48     <!-- 
    49         格式化sql语句
    50     -->
    51     <property name="format_sql">true</property>
    52     <!-- 
    53         session要从当前线程中产生
    54     -->
    55     <property name="current_session_context_class">thread</property>
    56     <!-- 
    57         加载映射文件
    58     -->
    59     <mapping resource="com/itheima09/hibernate/domain/Classes.hbm.xml" />
    60     <mapping resource="com/itheima09/hibernate/domain/Student.hbm.xml" />
    61 </session-factory>
    62 </hibernate-configuration>
    hibernate.cfg.xml
     1 import java.io.Serializable;
     2 import java.util.Set;
     3 
     4 public class Classes implements Serializable{
     5     private Long cid;
     6     private String name;
     7     private String description;
     8     private Set<Student> students;
     9     public Long getCid() {
    10         return cid;
    11     }
    12     public void setCid(Long cid) {
    13         this.cid = cid;
    14     }
    15     public String getName() {
    16         return name;
    17     }
    18     public void setName(String name) {
    19         this.name = name;
    20     }
    21     public String getDescription() {
    22         return description;
    23     }
    24     public void setDescription(String description) {
    25         this.description = description;
    26     }
    27     public Set<Student> getStudents() {
    28         return students;
    29     }
    30     public void setStudents(Set<Student> students) {
    31         this.students = students;
    32     }
    33 }
    Classes.java
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Classes">
     6         <id name="cid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="100"></property>
    11         <!-- 
    12             fetch 抓取策略
    13               join  通过做外链接
    14               select  默认值
    15               subselect
    16          -->
    17         <set name="students" cascade="all" fetch="subselect">
    18             <!-- 
    19                 key代表外键
    20                 用来关联classes表和student表,用于在hibernate低层生成sql语句
    21              -->
    22             <key>
    23                 <column name="cid"></column>
    24             </key>
    25             <!-- 
    26                 建立类与类之间的关联,用于客户端的编码
    27              -->
    28             <one-to-many class="com.itheima09.hibernate.domain.Student"/>
    29         </set>
    30     </class>
    31 </hibernate-mapping>
    Classes.hbm.xml
     1 import java.io.Serializable;
     2 
     3 public class Student implements Serializable{
     4     private Long sid;
     5     private String name;
     6     private String description;
     7     private Classes classes;
     8     
     9     public Classes getClasses() {
    10         return classes;
    11     }
    12     public void setClasses(Classes classes) {
    13         this.classes = classes;
    14     }
    15     public Long getSid() {
    16         return sid;
    17     }
    18     public void setSid(Long sid) {
    19         this.sid = sid;
    20     }
    21     public String getName() {
    22         return name;
    23     }
    24     public void setName(String name) {
    25         this.name = name;
    26     }
    27     public String getDescription() {
    28         return description;
    29     }
    30     public void setDescription(String description) {
    31         this.description = description;
    32     }
    33 }
    Student.java
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <hibernate-mapping>
     5     <class name="com.itheima09.hibernate.domain.Student">
     6         <id name="sid" length="5">
     7             <generator class="increment"></generator>
     8         </id>
     9         <property name="name" length="20"></property>
    10         <property name="description" length="100"></property>
    11         <!-- 
    12             column 为外键
    13          -->
    14         <many-to-one name="classes" column="cid" 
    15             class="com.itheima09.hibernate.domain.Classes" cascade="save-update">
    16         </many-to-one>
    17     </class>
    18 </hibernate-mapping>
    Student.hbm.xml
     1 import java.util.List;
     2 import java.util.Set;
     3 
     4 import org.hibernate.Session;
     5 import org.hibernate.Transaction;
     6 import org.junit.Test;
     7 
     8 import com.itheima09.hibernate.domain.Classes;
     9 import com.itheima09.hibernate.domain.Student;
    10 import com.itheima09.hibernate.utils.HibernateUtils;
    11 
    12 public class FetchTest extends HibernateUtils{
    13     @Test
    14     public void testCreateTable(){
    15         
    16     }
    17     
    18     /**
    19      * 获取到所有的班级的所有的学生
    20      *    如果采用默认的策略,会导致n+1条sql语句,n为classes表中的行数
    21      */
    22     @Test
    23     public void testGetAllClassesAndStudent(){
    24         Session session = sessionFactory.getCurrentSession();
    25         Transaction transaction = session.beginTransaction();
    26         List<Classes> classesList = session.createQuery("from Classes").list();
    27         for(Classes classes:classesList){
    28             Set<Student> students = classes.getStudents();
    29             for(Student student:students){
    30                 System.out.println(student.getName());
    31             }
    32         }
    33         transaction.commit();
    34     }
    35     
    36     /**
    37      * 获取cid为1的班级,再获取cid为1的班级的所有的学生
    38      */
    39     @Test
    40     public void testGetClassesAndStudent(){
    41         Session session = sessionFactory.getCurrentSession();
    42         Transaction transaction = session.beginTransaction();
    43         Classes classes = (Classes)session.get(Classes.class, 1L);
    44         Set<Student> students = classes.getStudents();
    45         for(Student student:students){
    46             System.out.println(student.getName());
    47         }
    48         transaction.commit();
    49     }
    50     
    51     /**
    52      * 查询cid为1,2,3,4的班级的学生
    53      */
    54     @Test
    55     public void testQueryStudentFromClassesIn(){
    56         Session session = sessionFactory.getCurrentSession();
    57         Transaction transaction = session.beginTransaction();
    58         List<Classes> classesList = session.createQuery("from Classes where cid in(1,2,3,4)").list();
    59         for(Classes classes:classesList){
    60             Set<Student> students = classes.getStudents();
    61             for(Student student:students){
    62                 System.out.println(student.getName());
    63             }
    64         }
    65         transaction.commit();
    66     }
    67 }
    FetchTest.java

    总结

    1、  研究对象是集合

    2、  经过分析,如果sql语句中含有了子查询,则用subselect效率比较高

    3、  如果页面上需要一次性把两张表的数据全部提取出来,用join效率比较高

    因为采用”join”为左外链接

    4、  如果用select,先查询班级,后查询学生,如果查询班级的个数超过1个,会导致n+1条sql语句

    5、  抓取策略是hibernate提供的一种优化方式而已

    延迟加载(懒加载)

         概念

           需要用到该数据的时候才要加载(详情请见笔记二)

    错误分析:

    错误一

     

    分析:person表不存在

    一般的原因是在hibernate.cfg.xml文件中没有加入该配置

    错误二

     

    错误原因:hibernate不认为该类是一个持久化类,因为在所有的映射文件中的class元素的name属性中没有发现该类

    错误三

     

    错误原因:找到了映射文件,但是映射文件中的class元素的name属性描述的类是一个不存在的类

    错误四

    错误原因: 在拼接sql语句的时候,映射文件中的property元素的name属性的值和持久化类的属性不一样,所以拼接不出来getter方法

    错误五

     

    错误原因:

    谨记:在实际开发中如果重写类的构造方法最好将省缺构造方法也写出

    错误六

     

    在执行save方法之前,必须手动赋值主键的值,因为在映射文件中,使用了assigned主键的生成机制。

    错误七

     

    错误原因: 该主键的生成策略说明了支持主键的自动增加,但是在该表中

    不支持这种

    错误八

        

      

           错误原因:

                  如果用当先线程获取session,crud操作必须在事务的环境下运行

    错误九

          

    分析:

    1、  在客户端

     

    试图通过显示保存classes来隐式保存student,但是在Classes.hbm.xml文件中的set元素中没有设置cascade属性

     

    错误十

          

    在Classes.hbm.xml文件中

     

         

    在客户端

         

    Student对象是从classes对象中获取到的,也就是说student对象是classes对象的关联对象。

    所以在没有解除classes与student关系之前,不能删除student。

    所以应该先解除关系:

    合群是堕落的开始 优秀的开始是孤行
  • 相关阅读:
    软件配置管理的作用?软件配置包括什么?
    火火恍恍惚惚
    什么是软件测试?软件测试的目的与原则
    软件生存周期及其模型是什么?
    试述软件的概念和特点?软件复用的含义?构件包括哪些?
    一台客户端有三百个客户与三百个客户端有三百个客户对服务器施压,有什么区别?
    numpy的broadcast是怎么做的
    python到底是解释型语言还是需要编译的?
    python:删除类实例,仅仅只有动态属性会被删除,类属性不会被删除
    jupyter的kernel莫名其妙找不到,莫名其妙就中断
  • 原文地址:https://www.cnblogs.com/biaogejiushibiao/p/9434544.html
Copyright © 2020-2023  润新知