Java框架之Hibernate

首先,上圖...


Hibernate 框架.png

上面的是hibernate中經(jīng)常用到的知識點,我們一個一個看.

一 工作流程

  • 讀取并解析配置文件
  • 讀取并解析映射信息,創(chuàng)建SessionFactory
  • 打開Sesssion
  • 創(chuàng)建事務(wù)Transation
  • 持久化操作
  • 提交事務(wù)
  • 關(guān)閉Session
  • 關(guān)閉SesstionFactory

jdbc 流程:

  • 加載驅(qū)動mysql
  • 獲取連接
  • 預(yù)編譯
  • 執(zhí)行sql
  • 將數(shù)據(jù)存入結(jié)果集
  • 關(guān)閉數(shù)據(jù)庫

jdbc和hibernate區(qū)別:

jdbc優(yōu)點:
SQL應(yīng)用靈活
數(shù)據(jù)庫移植
jdbc缺點:
 不便于維 代碼繁瑣 護   效率低
hibernate 框架 優(yōu)點:
 真正基于ORM模型
 脫離java代碼  降低耦合度
 操作簡單,易用
缺點:
    不便于操作表結(jié)構(gòu)復(fù)雜的sql
    不便于數(shù)據(jù)庫移植(跨數(shù)據(jù)庫移植)
    代替了jdbc技術(shù),是一個全封裝的框架,不便于調(diào)試bug
什么時候用hibernate框架

表數(shù)量少 結(jié)構(gòu)不復(fù)雜,快速應(yīng)用它來開發(fā)

hibernate中的緩存技術(shù):

1.只是一次連接數(shù)據(jù)庫,多次使用

  1. 數(shù)據(jù)是存在緩存區(qū)里的,操作:session.get() session.save(),session.delete().
    3.分為二級緩存:
    一級緩存:session 存在 內(nèi)存的緩存區(qū)中
    清理一級緩存的方式:
    clear() 方法清理緩存直接從硬盤中的數(shù)據(jù)庫讀取
    evict(對象) 執(zhí)行的是數(shù)據(jù)庫中的查詢,第一次查詢會失效
    二級緩存:sessionFactort 存在 硬盤中
    Hibernate 緩存執(zhí)行順序
    當(dāng) Hibernate 根據(jù) ID 訪問數(shù)據(jù)對象時,首先會從一級緩存 Session 中查找。若查 不到且配置了二級緩存,則會從二級.
    緩存中查找;若還查不到,就會查詢數(shù)據(jù)庫,把結(jié) 果按照 ID 放入到緩存中。執(zhí)行增、刪、改操作時,會同步更新緩存。
    二級緩存內(nèi)容分類
    根據(jù)緩存內(nèi)容的不同,可以將 Hibernate 二級緩存分為三類: (1)類緩存:緩存對象為實體類對象 (2)集合緩存:緩存對象為集合類對象 (3)查詢緩存:緩存對象為查詢結(jié)果
hibernate框架中g(shù)et方法和load方法獲取對象的方式有什么不同:

get和load方法都是根據(jù)id去獲得對應(yīng)數(shù)據(jù)的,但是獲得機制不同:如果使用get方法,hibernate會去確認該id對應(yīng)的數(shù)據(jù)是否存在,它首先會去session中去查詢(session緩存其實就hibernate的一級緩存),如果沒有,再去二級緩存中去查詢,如果再沒有,就去數(shù)據(jù)庫中查詢,仍然沒有找到的話,就返回null
而使用load方法的話,hibernate會認定該id對應(yīng)的數(shù)據(jù)一定存在,它也會先去session緩存中去查找,如果沒有找到,hibernate會根據(jù)lazy屬性值來確定是否使用延遲加載。如果lazy=‘true’ ,就使用延遲加載,返回該代理對象,等到真正訪問到該對象的屬性時才會去二級緩存中查詢,如果沒有,再去數(shù)據(jù)庫中查詢,如果還沒有,就拋出org.hibernate.ObjectNotFoundException異常。如果lazy='false' 則不使用延遲加載,這是load的訪問機制就和get一樣了。

事物的特性:

1.原子性(不許分割)
2.一致性(兩個事物可以有添加和減少)
3.隔離性(兩個事物在執(zhí)行過程中,相互不影響)
4.持久性: (兩個事物執(zhí)行完畢后,影響一直有效)

hibernate對象的狀態(tài)

1.對象的臨時狀態(tài) Emp e = new Emp("hah", 1000.0, 21, date);
2.對象的持久化狀態(tài) session.save(e);
st.commit();
3.對象的游離狀態(tài)session.close();
事物是連接java代碼和數(shù)據(jù)庫的橋梁

hibernate框架中表之間的關(guān)系:

一對多
hibernate中級聯(lián)刪除:更改級聯(lián)關(guān)系為 cascade="delect";
刪除班級,刪除學(xué)生 有外鍵
直接刪除:班級信息置為null 學(xué)生信息不變
:更改級聯(lián)關(guān)系為 cascade="delect" 根據(jù)外鍵,刪除當(dāng)前表及其有關(guān)系的其他表,刪除有外鍵有關(guān)系的表
一對多
在進行解除關(guān)系或者刪除的時候 One-to-many比較簡單,執(zhí)行的效率高 其他操作的時候many_to-one效率高
One-to-many 類和集合的關(guān)系
many-to-one 類和對象的關(guān)系
多對一(雙向)
以Student-classes表為例 一個班級有更多學(xué)生同樣更多學(xué)生在一個班級
建立 Student 和Classes的實體類

//Classes表中的屬性  注意學(xué)生集合
    private Integer c_id;
    private String  c_name;
    private Set<Student> stus;

  //student表中的屬性
    private Integer s_id;
    private String s_name;
    //建立關(guān)系: 多個學(xué)生 一個班級
    private Classes cls;

//classes表的映射文件
<hibernate-mapping>
    <class name="cn.lanou3g.vo.Classes" >
        <id name="c_id">
            <generator class="increment" />
        </id>
        <property name="c_name"/>
     
        <!-- 搭建一對多的關(guān)系    inverse是否維系關(guān)系 默認false
        cascade 級聯(lián)關(guān)系  save-update  保存或更新的時候維系關(guān)系
                        delete 級聯(lián)刪除-->
        <set name="stus" inverse="false" cascade="save-update">
        <!--從表的外鍵  -->
        <key column="c_id"></key>
        <!-- 指定對應(yīng)關(guān)系   它是stus對應(yīng)的實體類-->
        <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"/>
        <!-- 建立關(guān)系 cls 多對一  cascade 級聯(lián)關(guān)系-->
        <many-to-one name="cls" class="cn.lanou3g.vo.Classes" cascade="save-update">
         <!-- 這里的外鍵,要與one-to-many對應(yīng)的外鍵一致 -->
         <!--  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();
   
    }
    //保存學(xué)生 保存班級
    //@Test
    public void textaddStuandcls(){
       //新增班級
       Student stu = new Student();
       stu.setS_name("momo");
       //新增班級
       Classes cls = new Classes();
       cls.setC_name("java");
       //通過學(xué)生保存班級
       stu.setCls(cls);
       session.save(stu);
       ts.commit();
    }
    //更新學(xué)生 級聯(lián)保存班級
    //@Test
       public void textupdateStuandcls(){
         Student stu = (Student)session.get(Student.class, 1);
         stu.setS_name("lida");
         session.save(stu);
         ts.commit();
    }
    //給學(xué)生賦班級
    //@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();
    }
    //解除一個班級和所有學(xué)生之間的關(guān)系(注意保存班級)
    // 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);//級聯(lián)關(guān)系改為null
     session.update(cls);
     ts.commit();
    
    } 
}

多對多:
以course-student表為例 很多課程被很多學(xué)生選擇

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

//coutse表中的屬性
   private  Integer c_id;
   private String c_name;
   //建立聯(lián)系  多對多 多個課程被多了學(xué)生選擇
   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"/>
        <!-- 建立關(guān)系 cls 多對一  cascade 級聯(lián)關(guān)系-->
        <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"/>
        <!-- 建立關(guān)系 cls 多對一  cascade 級聯(lián)關(guān)系-->
        <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();
   
    }
    //添加一個新課程 添加一個新學(xué)生
    //先保存主表 在保存從表
    //@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();
       
    }
    //獲取學(xué)生 修改學(xué)生姓名  課程中添加修改后的學(xué)生姓名
    //@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和所有學(xué)生的關(guān)系
    //解除課程1和所欲學(xué)生之間的關(guān)系
    //多對多關(guān)系的刪除,只影響中間表,其他關(guān)聯(lián)表不動
    //設(shè)置學(xué)生為null
    //@Test
    public void textdel(){
       Course cours = (Course)session.get(Course.class, 1);
      cours.setStus(null);
      session.save(cours);
      ts.commit();
    }
    //刪除課程1下編號為1 的人
    //解除一個學(xué)生和一個課程的關(guān)系(值刪除中間表)
    //多對多中單條刪除用集合中的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"/>
    <!-- 直接指定對應(yīng)關(guān)系
    name  在當(dāng)前類中存在的類類型
     class name屬性對應(yīng)的全類型
     cascade 對當(dāng)前表的操作crud
    constrained="false"代表當(dāng)前表是主表-->
    <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"/>
    <!-- 直接指定對應(yīng)關(guān)系
    name  在當(dāng)前類中存在的類類型
     class name屬性對應(yīng)的全類型
     cascade 對當(dāng)前表的操作crud
    constrained="false"代表當(dāng)前表是主表
              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");
         //先保存從表中的關(guān)聯(lián)字段
         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();
     }
     //刪除用戶 刪除身份證 從主表中刪除  從表的也刪除
     //思路:通過主表獲取關(guān)聯(lián)字段
          //關(guān)聯(lián)字段放入主表
          // 刪除主表
    // @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"
為什么用它:
防止內(nèi)存溢出,遞歸調(diào)出方法

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

HQL語句:

  • 是指hibernate sql
  • 查詢?nèi)?/li>
  • 查詢某一個字段
  • 按條件查詢0
//分頁
     Query q = session.createQuery("from User");
    //起始位置
     q.setFirstResult(0);
    //一次展示多少條
     q.setMaxResults(5);
    //把查詢到的結(jié)果放入list集合
     List list = q.list();
     System.out.println(list);//遍歷并且輸出集合

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Hibernate: 一個持久化框架 一個ORM框架 加載:根據(jù)特定的OID,把一個對象從數(shù)據(jù)庫加載到內(nèi)存中OID...
    JHMichael閱讀 2,100評論 0 27
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,834評論 18 399
  • 這部分主要是開源Java EE框架方面的內(nèi)容,包括Hibernate、MyBatis、Spring、Spring ...
    雜貨鋪老板閱讀 1,572評論 0 2
  • Hibernate是一個開放源代碼的對象關(guān)系映射框架,它對JDBC進行了非常輕量級的對象封裝,它將POJO與數(shù)據(jù)庫...
    蘭緣小妖閱讀 1,289評論 1 18
  • 本文將分別討論輸入流、輸出流、字節(jié)流和字符流。一、以字節(jié)為單位的輸入流的框架圖: 從圖中可以看出以字節(jié)為單位的輸入...
    晏子小七閱讀 707評論 0 5

友情鏈接更多精彩內(nèi)容