Java框架之Hibernate

首先,上图...


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);//遍历并且输出集合

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • Hibernate: 一个持久化框架 一个ORM框架 加载:根据特定的OID,把一个对象从数据库加载到内存中OID...
    JHMichael阅读 1,931评论 0 27
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,293评论 18 399
  • 这部分主要是开源Java EE框架方面的内容,包括Hibernate、MyBatis、Spring、Spring ...
    杂货铺老板阅读 1,269评论 0 2
  • Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库...
    兰缘小妖阅读 1,173评论 1 18
  • 本文将分别讨论输入流、输出流、字节流和字符流。一、以字节为单位的输入流的框架图: 从图中可以看出以字节为单位的输入...
    晏子小七阅读 652评论 0 5