Hibernate框架入門

来源:https://www.cnblogs.com/cailijia52o/archive/2018/03/28/8661295.html
-Advertisement-
Play Games

Hibernate框架 一、什麼是hibernate? Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了非常輕量級的對象封裝,它將POJO與資料庫表建立映射關係,是一個全自動的orm框架,hibernate可以自動生成SQL語句,自動執行,使得Java程式員可以隨心所欲的使用 ...


Hibernate框架

一、什麼是hibernate?

            Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了非常輕量級的對象封裝,它將POJO與資料庫表建立映射關係,是一個全自動的orm框架,hibernate可以自動生成SQL語句,自動執行,使得Java程式員可以隨心所欲的使用對象編程思維來操縱資料庫。 Hibernate可以應用在任何使用JDBC的場合,既可以在Java的客戶端程式使用,也可以在Servlet/JSP的Web應用中使用,最具革命意義的是,Hibernate可以在應用EJB的J2EE架構中取代CMP,完成數據持久化的重任。                                                    

-----------360百科

  確切的說,hibernate其實就是個ORM(Object Relational Mapping)框架,程式員通過操作對象的方式來操作資料庫表的記錄。

二、快速入門

  1.從hibernate官網下載hibernate所需要的jar包

  2.搭建環境

      1) 將下載好的 jar包中lib\required的所有jar包導入web工程下的lib文件夾,這些是部署框架的核心jar包

   2) 導入用於連接資料庫的驅動jar包

   3) 導入日誌jar包(如log4j)

    
      

 

 

     

   3.編寫相對應的持久化類,並生成相對應的set/get,toString方法

/**
 * javaBean+屬於他的映射文件=持久化類
 * @author Administrator
 *
 */
public class Customer {
    //註意:這裡的數據類型使用包裝類,預設值為null
    private Long cust_id;
    private String cust_name;
    private Long cust_user_id;
    private Long cust_create_id;
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_linkman;
    private String cust_phone;
    private String cust_mobile;

    //省略set/get方法

}

 

    4.JavaBean所在的包下創建映射的配置文件(預設放在javabean同包下)

       1)* 預設的命名規則為:實體類名.hbm.xml

       2)* 在xml配置文件中引入約束(引入的是hibernate3.0的dtd約束,不要引入4的約束)

      位置:(hibernate-core-5.0.7.Final.jar\hibernate-core-5.0.7.Final.jar\org.hibernate\hibernate-configuration-3.0.dtd)    

 <!DOCTYPE hibernate-mapping PUBLIC 
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

       3) *寫相對應的映射,此是與資料庫進行映射

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- 配置類和表結構的映射 -->
    <class name="com.heima.domain.Customer" table="cst_customer">
        <!-- 配置主鍵 
             見到name屬性,JavaBean的屬性
             見到column屬性,是表結構的欄位
        -->
        <id name="cust_id" column="cust_id">
            <!-- 主鍵生成策略 --> 
            <generator class="native"/>
        </id>
        <!-- 配置其他的屬性 -->
        <property name="cust_name" column="cust_name"/>
        <property name="cust_user_id" column="cust_user_id"/>
        <property name="cust_create_id" column="cust_create_id"/>
        <property name="cust_source" column="cust_source"/>
        <property name="cust_industry" column="cust_industry"/>
        <property name="cust_level" column="cust_level"/>
        <property name="cust_linkman" column="cust_linkman"/>
        <property name="cust_phone" column="cust_phone"/>
        <property name="cust_mobile" column="cust_mobile"/>
    </class>
</hibernate-mapping>

    5.編寫Hibernate核心的配置文件

       1) 在src目錄下,創建名稱為hibernate.cfg.xml的配置文件

       2)XML中引入DTD約束,位置:(在hibernate-core-5.0.7.Final.jar\hibernate-core-5.0.7.Final.jar\org.hibernate\hibernate-configuration-3.0.dtd<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <!-- 記住:先配置sessionFactory標簽,一個資料庫對應一個sessionFactory標簽-->
    <session-factory>
        <!-- 必須配置的參數,4大參數,資料庫的方言 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://192.168.174.130:3306/hibernate_day01</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <!-- 資料庫的方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 可選配置 -->
        <!--顯示SQL語句,在控制台顯示  -->
        <property name="hibernate.show_sql">true</property>
        <!--格式化SQL語句,是的顯示語句更美觀  -->
        <property name="hibernate.format_sql">true</property>
        <!-- 開啟綁定本地的session -->
        <property name="hibernate.current_session_context_class">thread</property>
        <!-- 生成資料庫的表結構
        慎用create:會先刪除原有的表結構,然後再生成一個新的
           update:有則再原有基礎上增加數據,沒有則先創建再添加數據
        -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 映射配置文件 ,需要映入映射的配置文件-->
        <mapping resource="com/heima/domain/Customer.hbm.xml"/>
    </session-factory>
</hibernate-configuration>
 

     6.編寫測試

/**
 * 測試Hibernate框架
 * @author Administrator
 *
 */
public class Demo1 {
    /**
     * 測試保存用戶
     */
    @Test
    public void testSave1(){
        /**
         * 1.先載入配置文件
         * 2.創建sessionFactory對象,生成Session對象(會話)
         * 3.開啟事務
         * 5.編寫保存的代碼
         * 6.提交事務
         * 7.釋放資源
         */
        //1.先載入配置文件
        Configuration config=new Configuration();
        //預設載入src目錄下hibenate.cfg.xml的配置文件
        config.configure();
        //創建sessionFactory對象
        SessionFactory factory=config.buildSessionFactory();
        //創建session對象
        Session session=factory.openSession();
        //開啟事務
        Transaction tr=session.beginTransaction();
        //編寫保存的代碼
        Customer c=new Customer();
        //c.setCust_id(cust_id);  主鍵是自動遞增,不需要自己設置
        c.setCust_name("測試3");
        c.setCust_level("2");
        c.setCust_phone("110");
        //保存數據,操作對象就相當於操作資料庫的表結構
        session.save(c);
        //提交事務
        tr.commit();
        //釋放資源
        session.close();
        factory.close();
        
   }
}

   其中:

     1. Configuration類

      * Configuration對象用於配置並且啟動Hibernate。

      * Hibernate應用通過該對象來獲得對象-關係映射文件中的元數據,以及動態配置Hibernate的屬性,然後創建SessionFactory對象。

   2.SessionFactory

    *它是工廠類,是生成Session對象的工廠類

   *SessionFactory對象中保存了當前的資料庫配置信息和所有映射關係以及預定義的SQL語句。同時,SessionFactory還負責維護Hibernate的二級緩存。

三、代碼優化

    1.基於每次進行數據處理時都需要調用session,可以將它抽取出來,作為一個公共類

    

       綁定本地的Session

      1.現在的Hibernate框架中,使用session對象開啟事務,所以需要來傳遞session對象,框架提供了ThreadLocal的方式

      * 需要在hibernate.cfg.xml的配置文件中提供配置

          

* <property name="hibernate.current_session_context_class">thread</property>   <!--(註意:放在mapping標簽之前)-->

 

       * 使用SessionFactory的getCurrentSession()方法,獲取當前的Session對象。並且該Session對象不用手動關閉,線程結束了,會自動關閉

  public static Session getCurrentSession(){

            return factory.getCurrentSession();

        }

 

 

    * 註意:想使用getCurrentSession()方法,必須要先配置才能使用。

package com.itheima.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * Hibernate框架的工具類
 * @author Mr_佳先森
 *
 */
public class HibernateUtils {
    //ctrl+shift+x將小寫字母變成大寫,用於常量
    private static final Configuration CONFIG;
    private static final SessionFactory FACTORY;
    static{
        CONFIG=new Configuration().configure();
        FACTORY=CONFIG.buildSessionFactory();
    }
    /**
     * 從構造工廠中獲取sesson對象
     * openSession:作為一級緩存,可以提升查詢數據效率,但是當session生命周期
     * 結束,程式不可從緩存中獲取數據
     */
    public static Session getSession(){
        return FACTORY.openSession();
    }
    /**
     * getCurrentSession():將session封裝ThreadLocal中,每個線程調用線程不受
     * 其他線程的影響,即達到線程安全,又避免了悲觀鎖的效率低下的問題(即使用樂觀鎖)
     * 需要在核心配置文件中添加
     * @return
     */
    public static Session getCurrentSession(){
        return FACTORY.getCurrentSession();
    }
    public static void main(String[] args) {
        getSession();
    }
}

  

   其中session介面

    1.Session是在Hibernate中使用最頻繁的介面。也被稱之為持久化管理器。它提供了和持久化有關的操作,比如添加、修改、刪除、載入和查詢實體對象

     2.Session是線程不安全的

    3.Session有一個緩存,被稱之為Hibernate的一級緩存。每個Session實例都有自己的緩存

    4.session常用的方法:   

save()     delete()  get()  update()  save()  createQuery()

  

  2.調用工具類

    

/**
 * 測試Hibernate框架
 * @author Administrator
 *
 */
public class Demo1 {
    /**
     * 測試工具類
     */
    @Test
    public void testSave2(){
        Session session=HibernateUtils.getSession();
        //開啟事務
        Transaction tr=session.beginTransaction();
        //編寫保存的代碼
        Customer c=new Customer();
        //c.setCust_id(cust_id);  主鍵是自動遞增,不需要自己設置
        c.setCust_name("美美");
        c.setCust_level("2");
        c.setCust_phone("120");
        //保存數據,操作對象就相當於操作資料庫的表結構
        session.save(c);
        //提交事務
        tr.commit();
        //釋放資源
        session.close();
    }
    /**
     * 測試查詢方法,通過主鍵來查詢一條記錄
     */
    @Test
    public void testGet(){
        Session session=HibernateUtils.getSession();
        //這裡因為是查詢事務,所以無需要是事務
        //Transaction tr=session.beginTransaction();
        //這裡因為主鍵是Long類型,所以數字後面要加個L
        Customer coustomer=session.get(Customer.class, 2L);
        System.out.println(coustomer);
        //tr.commit();
        session.close();
    }
    /**
     * 測試刪除的方法
     * 註意:刪除或者修改之前,要先查詢在刪除或者修改
     */
    @Test
    public void testDel(){
        Session session=HibernateUtils.getSession();
        Transaction tr=session.beginTransaction();
        Customer c=session.get(Customer.class,2L);
        session.delete(c);
        tr.commit();
        session.close();
    }
    /**
     * 測試修改的方法
     */
    @Test
    public void testUpdate(){
        Session session=HibernateUtils.getSession();
        Transaction tr=session.beginTransaction();
        Customer c=session.get(Customer.class,3L);
        c.setCust_name("小蒼");
        c.setCust_level("3");
        session.update(c);
        tr.commit();
        session.close();
    }
    /**
     *添加或者修改
     */
    @Test
    public void testSaveOrUpdate(){
        Session session=HibernateUtils.getSession();
        Transaction tr=session.beginTransaction();
        //Customer c=new Customer();
        //註意:這裡的id值不能自己設置,否則會報錯,因為他是由框架管理
        //c.setCust_id(4L);
        //註意:查詢的id必須存在,否則會報空指針異常
        Customer c=session.get(Customer.class,3L);
        c.setCust_name("小菜");
        session.saveOrUpdate(c);
        tr.commit();
        session.close();
    }
    /**
     * 測試一個查詢的方法
     */
    @Test
    public void testSel(){
        Session session=HibernateUtils.getSession();
        Transaction tr=session.beginTransaction();
        //創建一個查詢的介面
        Query query=session.createQuery("from Customer");
        //查詢所有的數據select * from 表名
        List<Customer> list=query.list();
        for(Customer c:list){
            System.out.println(c);
        }
        tr.commit();
        session.close();
        
    }
    /**
     * 測試Hibernate框架正規寫法
     */
    @Test
    public void testSave3(){
        Session session=null;
        Transaction tr=null;
        try{
            session=HibernateUtils.getSession();
            tr=session.beginTransaction();
            Customer c=new Customer();
            c.setCust_name("小強");
            session.save(c);
            tr.commit();
        }catch(Exception e){
            tr.rollback();
            e.printStackTrace();
        }finally{
            session.close();
        }
    }
}

四、Hibernate的緩存   

     1.Hibernate框架提供了兩種緩存

         * 一級緩存  -- 自帶的不可卸載的.一級緩存的生命周期與session一致.一級緩存稱為session級別的緩存.

              * 二級緩存  -- 預設沒有開啟,需要手動配置才可以使用的.二級緩存可以在多個session中共用數據,二級緩存稱為是sessionFactory級別的緩存.

       2.Session對象的緩存概述

          * Session介面中,有一系列的java的集合,這些java集合構成了Session級別的緩存(一級緩存).將對象存入到一級緩存中,session沒有結束生命周期,那麼對象在session中存放                   著

       * 記憶體中包含Session實例 --> Session的緩存(一些集合) --> 集合中包含的是緩存對象!

    3.測試一級緩存存在

       

/**
     * 證明一級緩存存在
     */
    @Test
    public void run2(){
        Session session=HibernateUtils.getSession();
        Transaction tr=session.beginTransaction();
        User user=new User();
        user.setName("小明");
        user.setAge(20);
        //保存用戶
        Serializable id=session.save(user);
        System.out.println(id);
        //獲取對象,不會看到Sql語句
        User user2=session.get(User.class,id);
        System.out.println(user2.getName());
        
        tr.commit();
        session.close();
    }

    

 

五、Hibernate之事務

     1.什麼是事務

      事務就是邏輯上的一組操作,組成事務的各個執行單元,操作要麼全都成功,要麼全都失敗.

    2. 事務的特性

        * 原子性   -- 事務不可分割.

        * 一致性   -- 事務執行的前後數據的完整性保持一致.

        * 隔離性   -- 一個事務執行的過程中,不應該受到其他的事務的干擾.

        * 持久性   -- 事務一旦提交,數據就永久保持到資料庫中.

    3.關於解決數據丟失更新問題

       數據當涉及到併發訪問時,第一想到的是添加鎖機制,java中Thread 有添加synchronized關鍵字,資料庫中也有添加鎖的機制

     1)悲觀鎖

      即在資料庫語句中添加"for update"字句。A事務在操作該條記錄時,會把該條記錄鎖起來,其他事務是不能操作這條記錄的,只有當A事務提交後,鎖釋放了,其他                        事務才能操作該條記錄

     2)樂觀鎖

      在表結構中添加version欄位(屬性),預設值為0。A事務在操作完該條記錄,提交事務時,會先檢查版本號,如果發生版本號的值相同時,才可以提交事務。同時                        會更新版本號version=1;B事務操作完該條記錄時,提交事務時,會先檢查版本號,如果發現版本不同時,程式會出現錯誤。

     3)鎖使用方法

       悲觀鎖:   

session.get(Customer.class, 1,LockMode.UPGRADE);

      樂觀鎖:

      1)) 持久化類

public class User {
    private Integer id;
    private String name;
    private Integer age;
    //在javabean中添加屬性(樂觀鎖)
    private Integer version;
    
        //省略set/get toString()方法
    
}
    

       2)) 持久化類映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="com.itheima.domain.User" table="t_user">
            <id name="id" column="id">
            <!-- increment:獲取主鍵的最大值,進行+1,作為主鍵
                          缺點:不適合併發訪問
            -->
                <generator class="increment"></generator>
            </id>
            <!-- 樂觀鎖 ,就添加樂觀鎖的機制-->
            <version name="version"/>
            <property name="name" column="name" length="30"/>
            <property name="age" column="age"/>
        </class>
    </hibernate-mapping>

      3)) 此時可以寫兩個測試查詢的方法,進行debug調試

      關於version,當左邊更改數據時,發現自己的版本(0)與資料庫的版本(1)不一致,說明自己不是最新的版本,會放棄此次操作 

六、hibernate的幾種查詢方式(簡述)

      

/**
 * 測試查詢
 * @author Administrator
 *
 */
public class Demo4 {
    /**
     * 測試Query的查詢介面
     */
    @Test
    public void run1(){
        Session session=HibernateUtils.getCurrentSession();
        Transaction tr=session.beginTransaction();
        //查詢方式
        Query query=session.createQuery("from User");
        List<User> list=query.list();
        for(User user:list){
            System.out.println(user);
        }
        tr.commit();
        session.close();
    }
    /**
     * 添加查詢條件
     */
    @Test
    public void run2(){
        Session session=HibernateUtils.getCurrentSession();
        Transaction tr=session.beginTransaction();
        //查詢方式HQL(是Hibernate的獨有的,操作的是對象)
        Query query=session.createQuery("from User where age>?");
        //寫法二:Query query=session.createQuery("from User where age> :aa");
        //設置值:註意:這裡區別於JDBC(下標為1)
        query.setInteger(0,15);
        //query.setInteger("aa",15);
        List<User> list=query.list();
        for(User user:list){
            System.out.println(user);
        }
        tr.commit();
        session.close();
    }
    @Test
    public void run3(){
        Session session=HibernateUtils.getCurrentSession();
        Transaction tr=session.beginTransaction();
        //查詢方式HQL(是Hibernate的獨有的,操作的是對象)
        Query query=session.createQuery("from User where name like ?");
        query.setString(0,"%k%");
        List<User> list=query.list();
        for(User user:list){
            System.out.println(user);
        }
        tr.commit();
        session.close();
    }
    /**
     * Criteria介面:條件查詢,非常適合
     * 完全面對對象,沒有太多sql語句
     */
    @Test
    public void run4(){
        Session session=HibernateUtils.getCurrentSession();
        Transaction tr=session.beginTransaction();
        //先獲取到Criteria介面
        Criteria criteria=session.createCriteria(User.class);
        //沒有條件,查詢所有的數據
        List<User> list=criteria.list();
        System.out.println(list);
        tr.commit();
        session.close();
    }
    /**
     * 按條件查詢
     */
    @Test
    public void run5(){
        Session session=HibernateUtils.getCurrentSession();
        Transaction tr=session.beginTransaction();
        //先獲取到Criteria介面
        Criteria criteria=session.createCriteria(User.class);
        //添加查詢條件
        //Criterion是Hibnernate提供的條件查詢的對象,向傳入條件使用的工具類
        //Restrictions提供的靜態方法,拼接查詢條件
        criteria.add(Restrictions.gt("age",18));//gt為大於
        //繼續添加條件
        criteria.add(Restrictions.like("name","%s%"));
        //沒有條件,查詢所有的數據a
        List<User> list=criteria.list();
        System.out.println(list);
        tr.commit();
        session.close();
    }
    
}    

七、hibernate之級聯處理數據

     需求:假設一個客戶對應多個聯繫人,每個客戶信息的處理都會牽扯到相對應的聯繫人;相反,每一個聯繫人的處理也會牽扯到相對應的客戶

    1.創建持久化類

     1)在客戶中添加set集合關聯聯繫人

// 一個客戶對應多個聯繫人:放的是聯繫人的集合.(Hibernate預設使用的集合是Set集合.集合必須要自己手動初始化)
    private Set<LinkMan> linkMans = new HashSet<LinkMan>();

     2)在聯繫人中添加客戶屬性用於關聯客戶

 // 聯繫人關聯的客戶對象://這裡不要寫客戶的外鍵,要編寫一個對象,而這個對象千萬不能自己new,框架會幫你new
    private Customer customer;// ORM框架 Object 

    2.創建相對應的映射文件

     1)在客戶映射文件中配置關聯聯繫人的標簽set

<!-- 配置關聯對象 -->
        <!-- 
            set標簽:
                * name屬性:多的一方的集合的屬性名稱.
         -->
        <set name="linkMans">
            <!-- 
                key標簽 :
                    * column屬性:多的一方的外鍵的名稱.
            -->
            <key column="lkm_cust_id"></key>
            <!-- 
                one-to-many標簽:
                    * class屬性:多的一方的類全路徑
             -->
             <one-to-many class="com.clj.domain.LinkMan"/>
        </set>

     2) 在聯繫人映射文件中添加<many-to-one>標簽關聯客戶

<!-- 配置關聯對象: -->
        <!-- 
            many-to-one:標簽.代表多對一.
                * name        :一的一方的對象的名稱.
                * class        :一的一方的類的全路徑.
                * column    :表中的外鍵的名稱.
         -->
        <many-to-one name="customer" class="com.clj.domain.Customer" column="lkm_cust_id"/>

   3.編寫測試類

@Test
    // 向客戶 和 聯繫人中同時保存數據:
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 創建一個客戶
        Customer customer = new Customer();
        customer.setCust_name("張總");
        
        // 創建兩個聯繫人:
        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("秦助理");
        
        LinkMan linkMan2 = new LinkMan();
        linkMan2.setLkm_name("胡助理");
        
        // 建立關係:
        customer.getLinkMans().add(linkMan1);
        customer.getLinkMans().add(linkMan2);
        
        linkMan1.setCustomer(customer);
        linkMan2.setCustomer(customer);
        
        session.save(customer);
        session.save(linkMan1);
        session.save(linkMan2);
        
        tx.commit();
    }

八、級聯保存

    1.保存一個客戶的同時保存相對應的聯繫人

     1)在客戶映射文件中的<set>標簽中添加cascade=save-update屬性

<set name="linkmans" cascade="save-update">
            <!-- 需要出現子標簽 -->
            <key column="lkm_cust_id"/>
            <one-to-many class="com.clj.domain.Linkman"/>
        </set>

 

     2)添加測試類

級聯是有方向性:
* 保存客戶的時候級聯保存聯繫人.
    @Test
    /**
     * 測試級聯保存:
     * * 保存客戶 同時 級聯保存聯繫人.
      * 在set集合上配置cascade=”save-update”
     */
    public void demo3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 保存客戶:
        Customer customer = new Customer();
        customer.setCust_name("陳總");
        // 保存聯繫人:
        LinkMan man1 = new LinkMan();
        man1.setLkm_name("小花");

        // 建立關係:
        customer.getLinkMans().add(man1);
        man1.setCustomer(customer);
        
        // 執行保存操作:
        session.save(customer); // TransientObjectException:customer變為持久態對象,man 還是瞬時態對象.
        // session.save(man1);
        
        tx.commit();
    }

    2.保存聯繫人的同時保存相對應的客戶

     1)在聯繫人映射文件的<one-to-many>標簽中添加cascade=save-update屬性

 

<many-to-one name="customer" class="com.clj.domain.Customer" column="lkm_cust_id" cascade=”save-update”/>

 

     2) 編寫相對應的測試類

    @Test
    /**
     * 測試級聯保存:
     * * 保存聯繫人 級聯 保存客戶.
      * 在many-to-one上配置cascade=”save-update”
     */
    public void demo4(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 保存客戶:
        Customer customer = new Customer();
        customer.setCust_name("肖總");
        // 保存聯繫人:
        LinkMan man1 = new LinkMan();
        man1.setLkm_name("小嬌");

        // 建立關係:
        customer.getLinkMans().add(man1);
        man1.setCustomer(customer);
        
        // 執行保存操作:
        // session.save(customer); // TransientObjectException:customer變為持久態對象,man 還是瞬時態對象.
        session.save(man1);
        
        tx.commit();
    }

九、級聯刪除

     需求:刪除客戶的時候同時刪除客戶的聯繫人

     1)在客戶映射文件下的<set>標簽中配置cascade=delete屬性

        2 )  編寫相對應的測試類 

@Test
    /**
     * 測試級聯刪除
     * 刪除客戶的時候 刪除聯繫人:
     * 需要在Customer.hbm.xml中set標簽上配置cascade="delete"
     */
    public void demo6(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        Customer customer = session.get(Customer.class, 1l);
        session.delete(customer);
        
        // 不能級聯刪除的.
        /*Customer customer = new Customer();
        customer.setCust_id(1l);
        
        session.delete(customer);*/
        tx.commit();
    }

 

    需求:刪除聯繫人的時候同時刪除客戶

     1)在聯繫人映射文件下的<one-to-many>標簽中配置cascade=delete屬性

        2)編寫測試類

 

@Test
    /**
     * 測試級聯刪除
     * 刪除聯繫人 同時刪除 客戶:
     * 需要在LinkMan.hbm.xml中many-to-one標簽上配置cascade="delete"
     */
    public void demo7(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        LinkMan linkman = session.get(LinkMan.class, 1l);
        
        session.delete(linkman);
        
        tx.commit();
    }

 

    補充:

    級聯操作時,時常會因為雙向關聯會產生許多冗餘的數據,因為快照機制,在數據處理時進行數據的比對。

    此時得用到inverse="true"屬性

    

@Test
    /**
     * 更改聯繫人所屬的客戶
     * * 雙向關聯 會產生多餘的SQL:
     */
    public void demo8(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        LinkMan linkman = session.get(LinkMan.class, 5l);
        
        Customer customer = session.get(Customer.class, 4l);
        // 雙向關聯:
        linkman.setCustomer(customer);
        customer.getLinkMans().add(linkman);
        
        tx.commit();
    }

   此時,在客戶映射文件中添加inverse="trues"屬性,就可避免數據冗餘(一的一方放棄主鍵維護)

<set name="linkmans" cascade="save-update" inverse="true">
            <!-- 需要出現子標簽 -->
            <key column="lkm_cust_id"/>
            <one-to-many class="com.clj.domain.Linkman"/>
        </set>

十、Hibernate框架查詢方式

     1.OID檢索方式(通過唯一主鍵進行查詢)

      語法:session.get(對象名.class,主鍵Id);

/**
     * OId的方式查詢與對象導航的方式(兩者特點:只能查詢到一條數據)
     * 查詢客戶
     */
    @Test
    public void run1(){
        //先查詢1號客戶
        Session session=HibernateUtils.getCurrentSession();
        Transaction tr=session.beginTransaction();
        //查詢1:通過OId的方式查詢客戶(通過主鍵查詢)
        //先是有OID的方式查詢客戶
        Customer c=session.get(Customer.class,1L);
        System.out.println("===================");
        //查看該客戶聯繫人的集合
        //查詢2:對象導航的方式
        System.out.println(c.getLinkmans().size());
        tr.commit();
    }

     2.對象導航方式

       語法:new User().getRole().getRname()

/**
     * OId的方式查詢與對象導航的方式
     * 查詢聯繫人,屬於某個客戶
     */
    @Test
    public void run2(){
        Session session=HibernateUtils.getCurrentSession();
        Transaction tr=session.beginTransaction();
        Linkman man=session.get(Linkman.class,5L);
        System.out.println("====================");
        System.out.println(man.getCustomer().getCust_name());
        tr.commit();
    }

     3.HQL的查詢方式

     1) HQL(Hibernate Query Language) 是面向對象的查詢語言, 它和 SQL 查詢語言有些相似

      2)HQL 查詢語句是面向對象的,Hibernate負責解析HQL查詢語句, 然後根據對象-關係映射文件中的映射信息, 把 HQL 查詢語句翻譯成相應的 SQL 語句.

/**
 * HQL的檢索方式
 * @author Administrator
 *
 */
public class Demo2 {
    /**
     * 基本演示
     */
    @Test
    public <

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.為什麼要使用is 在vue的官網組件部分中,有明確的描述:當使用 DOM 作為模板時 (例如,使用 el 選項來把 Vue 實例掛載到一個已有內容的元素上),你會受到 HTML 本身的一些限制,因為 Vue 只有在瀏覽器解析、規範化模板之後才能獲取其內容。尤其要註意,像 <ul>、<ol>、<t ...
  • 來自:http://demo.doyoe.com/css3/justify/justify-form.htm 侵刪 ...
  • 前言 要分享的皮膚就是您現在看到的這款,雖然還有不少瑕疵,但是這個皮膚也算是大致完成。 本皮膚完全使用css樣式,無需申請js許可權,對移動端的也做了相應處理,也許您可以從其 中得到些借鑒。 當然皮膚其實是次要的,主要是分享一下這個解決方案。 這裡是github上的地址: "cnblogs skin" ...
  • 轉載(Singleton(單例)模式和Double-Checked Locking(雙重檢查鎖定)模式) 問題描述 現在,不管開發一個多大的系統(至少我現在的部門是這樣的),都會帶一個日誌功能;在實際開發過程中,會專門有一個日誌模塊,負責寫日誌,由於在系統的任何地方,我們都有可能要調用日誌模塊中的函 ...
  • 外觀模式應該是程式員最下意識用的一種模式,比如我們習慣性的對複雜系統做一個封裝介面。外觀模式其本質是對一堆複雜對象和應用的介面抽象,對它們進行封裝隔離,對於調用者來說只需要關係介面的實現,而不需要知道內部有哪些對象和調用。 作用 為模塊的一組介面提供一致的界面,定義了一個高層介面,這個介面使得這一模 ...
  • 針對消息隊列的數據積壓問題,我們主要做了三個方面的優化處理,取消同步鎖、ActiveMQ參數優化、本地雙隊列優化,通過這三個方面的優化基本解決了隊列數據積壓的問題。 ...
  • 月薪30K java程式員2018年java學習進階書籍推薦 ...
  • 內容:例子 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...