Java框架之Hibernate

作者: Miss_差不多 | 来源:发表于2017-11-27 20:44 被阅读117次

首先,上图...


Hibernate 框架.png

上面的是hibernate中经常用到的知识点,我们一个一个看.

一 工作流程

  • 读取并解析配置文件
  • 读取并解析映射信息,创建SessionFactory
  • 打开Sesssion
  • 创建事务Transation
  • 持久化操作
  • 提交事务
  • 关闭Session
  • 关闭SesstionFactory

jdbc 流程:

  • 加载驱动mysql
  • 获取连接
  • 预编译
  • 执行sql
  • 将数据存入结果集
  • 关闭数据库

jdbc和hibernate区别:

jdbc优点:
SQL应用灵活
数据库移植
jdbc缺点:
 不便于维 代码繁琐 护   效率低
hibernate 框架 优点:
 真正基于ORM模型
 脱离java代码  降低耦合度
 操作简单,易用
缺点:
    不便于操作表结构复杂的sql
    不便于数据库移植(跨数据库移植)
    代替了jdbc技术,是一个全封装的框架,不便于调试bug
什么时候用hibernate框架

表数量少 结构不复杂,快速应用它来开发

hibernate中的缓存技术:

1.只是一次连接数据库,多次使用

  1. 数据是存在缓存区里的,操作:session.get() session.save(),session.delete().
    3.分为二级缓存:
    一级缓存:session 存在 内存的缓存区中
    清理一级缓存的方式:
    clear() 方法清理缓存直接从硬盘中的数据库读取
    evict(对象) 执行的是数据库中的查询,第一次查询会失效
    二级缓存:sessionFactort 存在 硬盘中
    Hibernate 缓存执行顺序
    当 Hibernate 根据 ID 访问数据对象时,首先会从一级缓存 Session 中查找。若查 不到且配置了二级缓存,则会从二级.
    缓存中查找;若还查不到,就会查询数据库,把结 果按照 ID 放入到缓存中。执行增、删、改操作时,会同步更新缓存。
    二级缓存内容分类
    根据缓存内容的不同,可以将 Hibernate 二级缓存分为三类: (1)类缓存:缓存对象为实体类对象 (2)集合缓存:缓存对象为集合类对象 (3)查询缓存:缓存对象为查询结果
hibernate框架中get方法和load方法获取对象的方式有什么不同:

get和load方法都是根据id去获得对应数据的,但是获得机制不同:如果使用get方法,hibernate会去确认该id对应的数据是否存在,它首先会去session中去查询(session缓存其实就hibernate的一级缓存),如果没有,再去二级缓存中去查询,如果再没有,就去数据库中查询,仍然没有找到的话,就返回null
而使用load方法的话,hibernate会认定该id对应的数据一定存在,它也会先去session缓存中去查找,如果没有找到,hibernate会根据lazy属性值来确定是否使用延迟加载。如果lazy=‘true’ ,就使用延迟加载,返回该代理对象,等到真正访问到该对象的属性时才会去二级缓存中查询,如果没有,再去数据库中查询,如果还没有,就抛出org.hibernate.ObjectNotFoundException异常。如果lazy='false' 则不使用延迟加载,这是load的访问机制就和get一样了。

事物的特性:

1.原子性(不许分割)
2.一致性(两个事物可以有添加和减少)
3.隔离性(两个事物在执行过程中,相互不影响)
4.持久性: (两个事物执行完毕后,影响一直有效)

hibernate对象的状态

1.对象的临时状态 Emp e = new Emp("hah", 1000.0, 21, date);
2.对象的持久化状态 session.save(e);
st.commit();
3.对象的游离状态session.close();
事物是连接java代码和数据库的桥梁

hibernate框架中表之间的关系:

一对多
hibernate中级联删除:更改级联关系为 cascade="delect";
删除班级,删除学生 有外键
直接删除:班级信息置为null 学生信息不变
:更改级联关系为 cascade="delect" 根据外键,删除当前表及其有关系的其他表,删除有外键有关系的表
一对多
在进行解除关系或者删除的时候 One-to-many比较简单,执行的效率高 其他操作的时候many_to-one效率高
One-to-many 类和集合的关系
many-to-one 类和对象的关系
多对一(双向)
以Student-classes表为例 一个班级有更多学生同样更多学生在一个班级
建立 Student 和Classes的实体类

//Classes表中的属性  注意学生集合
    private Integer c_id;
    private String  c_name;
    private Set<Student> stus;

  //student表中的属性
    private Integer s_id;
    private String s_name;
    //建立关系: 多个学生 一个班级
    private Classes cls;

//classes表的映射文件
<hibernate-mapping>
    <class name="cn.lanou3g.vo.Classes" >
        <id name="c_id">
            <generator class="increment" />
        </id>
        <property name="c_name"/>
     
        <!-- 搭建一对多的关系    inverse是否维系关系 默认false
        cascade 级联关系  save-update  保存或更新的时候维系关系
                        delete 级联删除-->
        <set name="stus" inverse="false" cascade="save-update">
        <!--从表的外键  -->
        <key column="c_id"></key>
        <!-- 指定对应关系   它是stus对应的实体类-->
        <one-to-many class="cn.lanou3g.vo.Student"/>
        </set>
       
    </class>
</hibernate-mapping>

//Student的映射文件
<hibernate-mapping>
    <class name="cn.lanou3g.vo.Student">
        <id name="s_id">
           <generator class="increment"/>
        </id>
        <property name="s_name"/>
        <!-- 建立关系 cls 多对一  cascade 级联关系-->
        <many-to-one name="cls" class="cn.lanou3g.vo.Classes" cascade="save-update">
         <!-- 这里的外键,要与one-to-many对应的外键一致 -->
         <!--  column 指定从表的外键-->
         <column name="c_id"></column>
         </many-to-one>
      </class>
</hibernate-mapping>

public class TextCon {
     Session session=HibernateSessionFactory.getSession();
     Transaction ts=session.beginTransaction();
    @Test
    public void textConn(){
       //新建配置对象  目的是自动加载配置文件
       Configuration cfg = new Configuration();
       cfg.configure();//自动加载主配置文件
       //开启session工厂
       SessionFactory sf=cfg.buildSessionFactory();
   
    }
    //保存学生 保存班级
    //@Test
    public void textaddStuandcls(){
       //新增班级
       Student stu = new Student();
       stu.setS_name("momo");
       //新增班级
       Classes cls = new Classes();
       cls.setC_name("java");
       //通过学生保存班级
       stu.setCls(cls);
       session.save(stu);
       ts.commit();
    }
    //更新学生 级联保存班级
    //@Test
       public void textupdateStuandcls(){
         Student stu = (Student)session.get(Student.class, 1);
         stu.setS_name("lida");
         session.save(stu);
         ts.commit();
    }
    //给学生赋班级
    //@Test
    public void testUpdateStu(){
       Student stu = (Student)session.get(Student.class, 2);
       Classes cls = (Classes)session.get(Classes.class, 1);
       stu.setCls(cls);
       session.save(stu);
       ts.commit();
    }
    //解除一个班级和所有学生之间的关系(注意保存班级)
    // delect()  两表都删除
    //update 外键为null
    @Test
    public void testdelStuandcla(){
    Classes cls = (Classes)session.get(Classes.class, 1);
    //Student stu = (Student)session.get(Student.class, 1);
   //cls.setStus(null);//级联关系改为null
     session.update(cls);
     ts.commit();
    
    } 
}

多对多:
以course-student表为例 很多课程被很多学生选择

 //student表中的属性
    private Integer s_id;
    private String s_name;
    private Set<Course> cours;

//coutse表中的属性
   private  Integer c_id;
   private String c_name;
   //建立联系  多对多 多个课程被多了学生选择
   private Set<Student> stus;

//Course表中映射文件
<hibernate-mapping>
    <class name="cn.lanou3g.vo.Student">
        <id name="s_id">
           <generator class="increment"/>
        </id>
        <property name="s_name"/>
        <!-- 建立关系 cls 多对一  cascade 级联关系-->
        <set name="cours" table="student_course" cascade="all">
        <key column="s_id"/>
        <many-to-many class="cn.lanou3g.vo.Course" column="c_id"/>
       
        </set>
     
    </class>
</hibernate-mapping>

//student的映射文件
<hibernate-mapping>
    <class name="cn.lanou3g.vo.Course">
        <id name="c_id">
           <generator class="increment"/>
        </id>
        <property name="c_name"/>
        <!-- 建立关系 cls 多对一  cascade 级联关系-->
        <set name="stus" table="student_course" cascade="all">
        <key column="c_id"/>
        <many-to-many class="cn.lanou3g.vo.Student" column="s_id"/>
       
        </set>
     
    </class>
</hibernate-mapping>

public class TextCon {
     Session session=HibernateSessionFactory.getSession();
     Transaction ts=session.beginTransaction();
    @Test
    public void textConn(){
       Configuration cfg = new Configuration();
       cfg.configure();
       SessionFactory sf = cfg.buildSessionFactory();
   
    }
    //添加一个新课程 添加一个新学生
    //先保存主表 在保存从表
    //@Test
    public void textinsert(){
       Student stu = new Student();
       Course cours =new Course();
       stu.setS_name("box");
       cours.setC_name("java");
       Set<Student> stus = new HashSet<Student>();
       stus.add(stu);
       cours.setStus(stus);
       session.save(cours);
       ts.commit();
       
    }
    //获取学生 修改学生姓名  课程中添加修改后的学生姓名
    //@Test
    public void textUpdatestu(){
       Student stu = (Student)session.get(Student.class, 1);
       stu.setS_name("灿烈");
       Course cours = (Course)session.get(Course.class, 1);
       Set<Student> stus = new HashSet<Student>();
       stus.add(stu);
       cours.setStus(stus);
       session.save(cours);
       ts.commit();
    }
    //解除课程1和所有学生的关系
    //解除课程1和所欲学生之间的关系
    //多对多关系的删除,只影响中间表,其他关联表不动
    //设置学生为null
    //@Test
    public void textdel(){
       Course cours = (Course)session.get(Course.class, 1);
      cours.setStus(null);
      session.save(cours);
      ts.commit();
    }
    //删除课程1下编号为1 的人
    //解除一个学生和一个课程的关系(值删除中间表)
    //多对多中单条删除用集合中的remove()进行删除
    @Test
    public void textdelmid(){
       Course cours = (Course)session.get(Course.class, 2);
       Student stu = (Student)session.get(Student.class, 2);
      Set<Course> c = stu.getCours();
      c.remove(cours);
      session.save(cours);
      ts.commit();
    }
    
}

一对一
以person-card为例 一个人只有一个身份证

//card的属性    
    private Integer c_id;
    private String c_name;
    private Person c_p;

//person的属性
     private Integer p_id;//主键
     private String  p_name;
     private Card p_c;

//card的映射文件
<hibernate-mapping>
<!-- 引入实体类的全类名 -->
    <class name="cn.lanou3g.entity.Card">
    <!-- 主键字段 -->
    <id name="c_id">
      <generator class="increment"/>
    </id>
   
    <!--普通字段  -->
    <property name="c_name"/>
    <!-- 直接指定对应关系
    name  在当前类中存在的类类型
     class name属性对应的全类型
     cascade 对当前表的操作crud
    constrained="false"代表当前表是主表-->
    <one-to-one name="c_p" class="cn.lanou3g.entity.Person" cascade="all" constrained="true"/>
   </class>

//Person的映射文件
<hibernate-mapping>
<!-- 引入实体类的全类名 -->
    <class name="cn.lanou3g.entity.Person">
    <!-- 主键字段 -->
    <id name="p_id">
      <generator class="increment"/>
    </id>
   
    <!--普通字段  -->
    <property name="p_name"/>
    <!-- 直接指定对应关系
    name  在当前类中存在的类类型
     class name属性对应的全类型
     cascade 对当前表的操作crud
    constrained="false"代表当前表是主表
              true 代表从表-->
    <one-to-one name="p_c" class="cn.lanou3g.entity.Card" cascade="all" constrained="false"/>
  </class>
</hibernate-mapping>

public class text {
    Session session = HibernateSessionFactory.getSession();
     Transaction ts=session.beginTransaction();
   //自动建表
    
@Test
    public void textConn(){
       //新建配置对象  目的是自动加载配置文件
       Configuration cfg = new Configuration();
       cfg.configure();//自动加载主配置文件
       //开启session工厂
       SessionFactory sf=cfg.buildSessionFactory();
   
    }
// 同时添加人(主表)和身份证
  // @Test
     public void textInser(){
         Person p = new Person("梁靖");
         Card c = new Card("152727199603111025");
         //先保存从表中的关联字段
         c.setC_p(p);
        // p.setP_c(c);
         //保存从表
          session.save(c);
          ts.commit();
   }
   //修改id为1的姓名
    // @Test
     public void textUpdate(){
        Person p = (Person)session.get(Person.class, 2);
        p.setP_name("梁敏");
        session.save(p);
        ts.commit();
     }
     //删除用户 删除身份证 从主表中删除  从表的也删除
     //思路:通过主表获取关联字段
          //关联字段放入主表
          // 删除主表
    // @Test
     public void textdelect(){
        Person p = (Person)session.get(Person.class, 2);
//         Card p_c =p.getP_c();
//         p.setP_c(p_c);
         session.delete(p);
         ts.commit();
     }
}

懒加载

映射文件中加入属性lazy="true"
为什么用它:
防止内存溢出,递归调出方法

  • 解决:
    1.去掉任何一方的toString()
    2.在不需要查询的一方的配置文件中加入lazy="true"

HQL语句:

  • 是指hibernate sql
  • 查询全部
  • 查询某一个字段
  • 按条件查询0
//分页
     Query q = session.createQuery("from User");
    //起始位置
     q.setFirstResult(0);
    //一次展示多少条
     q.setMaxResults(5);
    //把查询到的结果放入list集合
     List list = q.list();
     System.out.println(list);//遍历并且输出集合

相关文章

网友评论

    本文标题:Java框架之Hibernate

    本文链接:https://www.haomeiwen.com/subject/dbtjbxtx.html