hibernate 底層知識拓展

實體類規範(javaBean規範)
1.提供無參構造方法
2.成員變量私有化提供get/set方法
double 表示學分 0-100.0 沒考試 0
Double 有null值 缺考 用空值表示03.基本數據類型儘量使用包裝類型(可以多表示一個值null例如考試分數 缺考和0分)
4.實體中必須要提供一個與表中的主鍵相對應的屬性id
hibernate是通過主鍵來區別對象是否相同
5.不要使用final修飾實體類(代理對象是要繼承該類的)
主鍵的類型
1.自然主鍵
輸入人的時候 人的身份證號 保證了 非空不重複  複合主鍵的貼點

但是身份證號 本身是業務字段  可以作爲主鍵使用 叫做自然主鍵

2.代理主鍵(常用)
當找不到主鍵的時候(沒有業務字段符合主鍵的規則)
搞一個沒有任何意義的主鍵id列 作爲主鍵 就是爲了非空不重複 叫做代理主鍵
主鍵生成策略(7種)
identity:主鍵自增 有數據庫來維護主鍵 錄入的時候不需要指定主鍵

increment:主鍵自增 由hibernate來維護主鍵 每次插入前會先查詢表中 id
最大值 +1 作爲新主鍵
效率不高每次都要查詢 如何10個人同時要保存 可能會出現線程問題

sequence:Oracle中的主鍵生策略 序列
hilo:高低位算法(數據庫中的主鍵自增算法原理)由hiernate來維護主鍵hibernate自己算一下(無意義)

native:hilo +sequence + identity 自動三選一 檢測你是什麼數據庫

mysql就identity Oracle就sequence 如果沒有就 用hilo 但是世界上沒有一個 不支持自增和序列的數據庫 其實就是21 

uuid:產生一個隨機的字符串作爲主鍵 主鍵類型必須爲string類型 

assigned:自然主鍵生成策略(沒策略)hibernate不會管理 由開發人自己錄入

三種狀態

1.瞬時態 沒有id 沒有和session關聯(這裏的關聯是指和緩存關聯)
2.持久態 有id 有關聯(這裏的關聯是指和緩存關聯)
3.遊離態 有id 沒有關聯(這裏的關聯是指和緩存關聯)

測試:save get 多次 打印的語句
結論:就是將我們想要同步數據庫的數據 所對應的對象轉換成持久態
/* hibernate中對象的三種狀態
     * 
     */
    @Test
    public void  fun(){
        //獲取session
        Session session = HibernateUtils.getSession();
        //開啓事物
        Transaction transaction = session.beginTransaction();
        //包裹語句
        //*******************************
        User user = new User();   //瞬時態 沒有id  沒有和session關聯
        user.setUsername("wl");
        user.setPassword("123456");

        session.save(user); //持久態  有id 有和session關聯
        // update delete  get  這三個方法是從 什麼態  轉  成什麼態
        //*********************************
        //提交事務
        transaction.commit();
        //關閉資源
        session.close(); //遊離態  有id  沒有和session關聯

        }

這裏寫圖片描述

一級緩存與快照(系統實現的 將以下的實現的原理)
1一級緩存測試 get多次 打印的語句

@Test
    public void  fun2(){
        //獲取session
        Session session = HibernateUtils.getSession();
        //開啓事物
        Transaction transaction = session.beginTransaction();
        //包裹語句
        //*******************************
        //測試一下hibernate 中的緩存
        User user1 = session.get(User.class, 1);
        User user2 = session.get(User.class, 1);
        User user3=      session.get(User.class, 1);
        User user4 = session.get(User.class, 1);
        User user5 = session.get(User.class, 1);
        //1.生成幾條sql語句
        //2.下面打印的結果
        //思考:爲什麼?
        //hibernate 的緩存機制
        //第一次   再一次

        System.out.println(user2==user5);

        //*********************************
        //提交事務
        transaction.commit();
        //關閉資源
        session.close(); //遊離態  有id  沒有和session關聯

        }

這裏寫圖片描述
2.快照 測試 get後 修改兩次名字 打印的語句

@Test
    //快照測試
    public void  fun4(){
        //獲取session
        Session session = HibernateUtils.getSession();
        //開啓事物
        Transaction transaction = session.beginTransaction();
        //包裹語句
        //*********************************
        User user = session.get(User.class, 1);
        user.setUsername("pp");
        user.setUsername("dpp");
        session.update(user);
        //*********************************
        //提交事務
        transaction.commit();
        //關閉資源
        session.close(); //遊離態  有id  沒有和session關聯

        }

這裏寫圖片描述
3.測試
瞬時態 -> 遊離態->持久態
new對象 -> 設置id -> update -> get

事物
        Transaction transaction = session.beginTransaction();
        //包裹語句
        //*********************************
        User user = new User();//瞬時態 沒有id  和session中的緩存 沒有關聯
        user.setId(1);        // 遊離態 有id   和session中的緩存 沒有關聯

        //從數據庫返回結果集 是保存進緩存和快照中
        //update 時 把這個要更新的對象 放入緩存中(跟快照沒關係)
        session.update(user); //持久態 有id  和session中的緩存 有關聯

        //get查詢時  去緩存中 查找  看有沒有該id的對象
        User u = session.get(User.class, 1);
        //問:打印幾條語句  爲什麼


        //*********************************
        //當事物提交的時候  
        //hibernate 會 對比 快照 和緩存中的對象是否相同
        //不相同 會把緩存中的對象 同步到數據庫

        //提交事務
        transaction.commit();
        //關閉資源
        session.close(); //遊離態  有id  沒有和session關聯

        }

指定事物的隔離級別

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate配置根標籤 -->
<hibernate-configuration>
    <!-- session-factory 相當於數據庫連接池 -->
    <session-factory>
        <!-- 加載了數據庫的驅動類 基礎設置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/a_hibernate_01</property>
        <!-- hibernate方言 配置使用哪個類 全限定類名 org.hibernate.dialect.MySQLDialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 在控制檯輸出sql語句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 美化sql語句 -->
        <property name="hibernate.format_sql">true</property>
        <!-- hbm2ddl.auto 是否自動生成表結構 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
                <!-- 
                    通過hibernate 來設置事物的隔離級別 
                    ## specify a JDBC isolation level       
                    #hibernate.connection.isolation 1|2|4|8
                    隔離級別是用一個字節存儲的 
                    0001            1
                    0010            2   
                    0100            4
                    1000            8 -->
                    <property name="hibernate.connection.isolation">4</property>
                    <!-- 使用getCurrentSession 必須配置一下 -->
                    <!-- 注意當你使用 getCurrentSession時 不需要你手動關閉session 系統會幫你關閉 -->
                    <property name="hibernate.current_session_context_class">thread</property>
                    1.髒讀
                    2.可重複讀
                    3.幻讀
                    READ UNCOMMITTED    讀未提交   1  2  3
                    READ COMMITTED      讀已提交      2  3 
                    REPEATABLE READ     可重複讀      3     
                    SERIALIZABLE            串行化(只能一個一個的訪問:效率非常的低) 
                     -->


        <!-- 注意:映射實體類 全文件名 從包名開始 -->
        <!-- 讓配置文件知道有你這個實體類 -->
        <mapping resource="com/lanou3g/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

設置可以獲取當前session 與當前線程綁定的

1.thread

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate配置根標籤 -->
<hibernate-configuration>
    <!-- session-factory 相當於數據庫連接池 -->
    <session-factory>
        <!-- 加載了數據庫的驅動類 基礎設置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/a_hibernate_01</property>
        <!-- hibernate方言 配置使用哪個類 全限定類名 org.hibernate.dialect.MySQLDialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 在控制檯輸出sql語句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 美化sql語句 -->
        <property name="hibernate.format_sql">true</property>
        <!-- hbm2ddl.auto 是否自動生成表結構 -->
        <property name="hibernate.hbm2ddl.auto">update</property>

                    <property name="hibernate.connection.isolation">4</property>
                    <!-- 使用getCurrentSession 必須配置一下 -->
                    <!-- 注意當你使用 getCurrentSession時 不需要你手動關閉session 系統會幫你關閉 -->
                    <property name="hibernate.current_session_context_class">thread</property>

        <!-- 注意:映射實體類 全文件名 從包名開始 -->
        <!-- 讓配置文件知道有你這個實體類 -->
        <mapping resource="com/lanou3g/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

注意:
1.配置配置文件
2.調用getCurrentSession獲取session 當事務提交 session會自動關閉 不需要手動關閉

創建實體類

public class User {
    private  int id;
    private String username;
    private  String password;

    public User() {
        super();
        // TODO Auto-generated constructor stub
    }
    public User(int id, String username, String password) {
        super();
        this.id = id;
        this.username = username;
        this.password = password;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
    }



}

簡單的分裝一個獲取session的方法

/*
 * 簡單封裝
 */
public class HibernateUtils {
    // 把sessionFactory寫成成員變量
    private static SessionFactory sessionFactory;
    static {
        // 加載配置文件
        Configuration configuration = new Configuration().configure();
        // 創建session工廠
        sessionFactory = configuration.buildSessionFactory();
    }
    // 返回session的方法
    public static Session getSession() {
        return sessionFactory.openSession();
    }
    // 返回當前session的方法
    public static Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }
}

獲取session

public class UserDao {

    public void saveUser(User user) {
            //獲取當前的session
            Session session = HibernateUtils.getCurrentSession();
            session.save(user);
    }
}

獲取當前的session

public class UserService {
    private  UserDao dao = new UserDao();

        public void addUser(User user) {
                    //獲取當前的session
            Session session = HibernateUtils.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            //調用dao層方法失敗了怎麼辦?


            try {
                dao.saveUser(user);
            } catch (Exception e) {
                //可以使用異常來處理.  失敗之後會報個異常.
                e.printStackTrace();
                //直接回滾事物  rollback
                transaction.rollback();
            }

            transaction.commit();
        }
}
發佈了92 篇原創文章 · 獲贊 42 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章