框架之Hibernate01

1      框架體系結構

 

2     hibernate入門

1   ORM框架

Object:對象,java對象,此處特指JavaBean

Relational:關係,二維表,數據庫中的表。

Mapping :映射|映射元數據,對象中屬性,與表的字段,存在對應關係。

      

ORM 對象和表的映射,就是通過將Java對象映射到數據庫表,通過操作Java對象,就可以完成對數據表的操作

 

Hibernate是一個數據持久化層的ORM框架,Hibernate提供了對關係型數據庫增刪改成操作,大大簡化了數據訪問層繁瑣的重複性代碼

 

 

2   主流的ORM框架

n Hibernate最流行ORM框架,通過對象-關係映射配置,可以完全脫離底層SQL

n MyBatis  是apache的一個開源項目 iBatis,支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架

n  輕量級的dao層組件(不算框架):Apache DBUtils 、Spring JDBCTemplate

 

 

3      入門案例【掌握】

1  編寫流程

  1. 創建數據庫和表

  2. 導入jar包

  3. 創建一個持久化類,編寫映射文件 hibernate mapping(*.hbm.xml)

  4. 編寫核心配置文件(hibernate.cfg.xml)--> 配置獲得鏈接等參數

  5 使用api測試

1   數據庫和表

create database contacts;
use contact;
create table t_user(
  id int auto_increment primary key,
  name varchar(50),
  pwd varchar(30)
);  

2   導入jar包

l需要導入的jar包(一共9個)

Lib-required: 共8個

Mysql-connector-java-5.1.39-bin,jar

 

3   編寫JavaBean + 映射文件

注意:上面兩個文件需要在同包下,映射文件爲 :類名.hbm.xml

關於*.hbm.xml的書寫規範可以直接在hibernate-release-4.1.1.Final文件夾中搜索*.hbm.xml

public class User {
    private Integer uid;
    private String username;
    private String password;
public Integer getUid() {
         return uid;
    }
    public void setUid(Integer uid) {
         this.uid = uid;
    }
    public String getUsername() {
         return username;
    }
    public void setUsername(String username) {
         this.username = username;
    }
    public String getPassword() {
         return password;
    }
}

<!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.chinasoft.entity.User" table="t_user">
         <!-- 主鍵  access=field  直接讀取字段值,不會調用setter和getter方法-->
        <id name="uid" type="java.lang.Integer">
            <column name="id" />
            <!-- 固定值:主鍵生成策略,使用數據庫本地的方式(mysql自增,oracle序列) -->
            <generator class="native" />
        </id>
       
        <!-- 普通屬性 -->
        <property name="username" type="java.lang.String">
            <column name="name" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="pwd" />
        </property>
</class>
</hibernate-mapping>


注意點:實體類需要滿足以下條件

1.提供一個無參數public訪問控制符的構造器

2.提供一個標識屬性用於映射數據表主鍵字段

3.所有屬性提供public訪問控制符的set  get方法(javaBean)

4. 標識屬性應儘量使用基本數據類型的包裝類型(包裝類型可以表示null,基本數據類型不可以)

5. 不要用final修飾實體 (將無法生成代理對象進行優化)

4   編寫核心配置文件

  位置:src目錄下

  名稱:hibernate.cfg.xml

關於hibernate.cfg.xml的書寫規範:在hibernate-release.4.1.1.Final中搜索

Ctrl+shift+t : 打開open Type窗口

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <!-- SessionFactory,相當於之前學習連接池配置 -->
    <session-factory>
         <!-- 基本4項 -->
         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///contacts</property>
         <property name="hibernate.connection.username">root</property>
         <property name="hibernate.connection.password">root</property>
         <!--數據庫方言,會針對不同的數據庫生成有差異的sql語句 -->
 <property name="hibernate.dialect"> org.hibernate.dialect.MySQL5Dialect</property>
<!—-是否顯示sql語句 -->
<property name="show_sql">true</property>
<!—格式化sql語句 -->
<property name="format_sql">true</property>
         <!-- 添加映射文件:注意是路徑不是包名 -->
         <mapping resource="com/test/hibernate/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>


5   測試

@Test
    public void testInsert(){
         User user = new User();
         user.setUsername("偉哥哥");
         user.setPassword("1234");
        
        
         //1 加載配置文件(hibernate.cfg.xml)獲得核心配置對象
         Configuration config = new Configuration().configure();
        
         //2 獲得工廠 SessionFactory,相當於連接池
         //hibernate4.0 之前這樣創建
         //SessionFactory factory = config.buildSessionFactory();
        
         ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
         SessionFactory factory = config.buildSessionFactory(serviceRegistry);
        
         //3獲得會話session,相當於鏈接Connection
         Session session = factory.openSession();
         //4 開啓事務
         Transaction transaction = session.beginTransaction();
        
        //操作
         session.save(user);
        
         //5 提交事務 | 回滾事務
         transaction.commit();
         //6 釋放資源--關閉session
         session.close();
         //7 釋放資源--關閉工廠factory
         factory.close();
    }  

 

4      api詳解【多練】

1   體系結構

PO:

      PersistentObject

       持久化對象

ORM:

O:Object

R: Relational

M:Mapping

對象關係映射

2   Configuration 配置對象

  Configuration是hibernate 核心配置文件種類

        hibernate.cfg.xml通常使用xml配置文件,可以配置內容更豐富。

<session-factory>
         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
         <property name="hibernate.connection.url">jdbc:mysql:///contacts</property>
         <property name="hibernate.connection.username">root</property>
         <property name="hibernate.connection.password">root</property>
 
<!-- 方言:爲不同的數據庫,不同的版本,生成sql語句(DQL查詢語句)提供依據
             * mysql 字符串 varchar
             * orcale 字符串 varchar2
         -->
         <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect </property>
 
<!--是否顯示sql語句 -->
         <property name="show_sql">true</property>
<property name="hibernate.format_sql">true</property>
 
<!-- 自動創建表(瞭解),學習中使用,開發不使用的。
             * 取值:
             update:【】
                  如果表不存在,將創建表。
                  如果表已經存在,通過hbm映射文件更新表(添加)。(映射文件必須是數據庫對應)
                      表中的列可以多,不負責刪除。
             create :如果表存在,先刪除,再創建。程序結束時,之前創建的表不刪除。【】
             create-drop:與create幾乎一樣。如果factory.close()執行,將在JVM關閉同時,將創建的表刪除了。(測試)
             validate:校驗 hbm映射文件和表的列是否對應,如果對應正常執行,如果不對應拋出異常。(測試)
         -->
         <property name="hbm2ddl.auto">update</property>
 
<!-- 添加映射文件 -->
         <mapping resource="com/test/hibernate/User.hbm.xml"/>
</session-factory>

User.hbm.xml


<class name="com.test.hibernate.User" table="user">
        <id name="uid" column="id">
            <generator class="native"/>
        </id>
        <property name="username" column="name"></property>
       <property name="password" column="pwd"></property>
</class>


Configuration的其他方法:

通過file創建Configuration對象:new Configuration().configure(file)

通過路徑創建Configuration對象:new Configuration().configure(path)

通過代碼向Configuation中添加mapping resourcenew Configuration().addClass(User.class)

 

3   SessionFactory工廠

SessionFactory 相當於java web連接池,用於管理所有session

獲得sessionFactory方式:

 1.hibernate4之前的獲取方式:config.buildSessionFactory();

 2.hibernate4之後的獲取方式:在hibernate4之後,所有的基於hibernate的配置或者服務都應該向ServiceRegistery註冊,所以可以通過如下代碼獲取

ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
SessionFactory factory = config.buildSessionFactory(serviceRegistry);


  SessionFactory線程安全,可以是成員變量,多個線程同時訪問時,不會出現線程併發訪問問題。

  提供api:

                 //打開一個新的會話 session

factory.openSession();

 

              //獲得當前線程中綁定的會話session,當事務中有多個數據庫操作的時候,需要保證操作數據庫的session同一個

factory.getCurrentSession();

注意:要使用factory.getCurrentSession方法,需要在hibernate.cfg.xml添加一條配置

<!-- 與本地線程綁定 -->
<property name=" hibernate.current_session_context_class ">thread</property>


4   Session 的基本使用

l  Session 相當於 JDBC的 Connection ,主要用來操作數據庫

l  Session具有一個緩存,位於緩存中的對應叫做持久化對象

      

l  使用Session實現數據庫的增刪改查

  save 保存

update 更新

delete 刪除

get 通過id查詢,立刻發送sql語句

createQuery("hql")  獲得Query對象

createCriteria(Class) 獲得Criteria對象

 

注意:在hibernate中刪除、更新等操作都是通過主鍵來操作的,所以要求數據庫和實體類必須有主鍵。

 private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;
   
    @Before
    public void init() {
         // 1 加載配置文件(hibernate.cfg.xml)獲得核心配置對象
         Configuration config = new Configuration().configure();
         // 2創建session工廠
         ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties())
                  .buildServiceRegistry();
         sessionFactory = config.buildSessionFactory(serviceRegistry);
         // 3.獲得會話session,相當於鏈接Connection
         session = sessionFactory.openSession();
         // 4.開啓事務
         transaction = session.beginTransaction();
    }
   
    @After
    public void destory() {
         //1. 提交事務 | 回滾事務
         transaction.commit();
         //2.釋放資源--關閉session
         session.close();
         //3.釋放資源--關閉工廠factory
         sessionFactory.close();
    }
   
   
    /***
     * 保存用戶
     */
    @Test
    public void testInsert(){
         User user = new User();
         user.setUsername("偉哥哥");
         user.setPassword("1234");
         //1.操作
         session.save(user);
    }
   
 
    /**
     * 查詢用戶
     */
    @Test
    public void queryUser(){
         //參照下面代碼
User user = (User)session.get(User.class, 1);
         System.out.println(user);
    }
   
//使用hql語言(面向對象)做查詢
Query query = session.createQuery("from User");
List<User> list = query.list();
System.out.println(list);
 
 
//使用QBC :criteria語言(面向對象)做查詢
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
System.out.println(list);
 
 
 
    /**
     * 修改用戶
     */
    @Test
    public void modifyUser(){
         User user = new User();
         user.setUid(11);
         user.setUsername("haha");;
         user.setPassword("1234");
         //更新操作
         session.update(user);
    }
   
    /**
     * 刪除用戶
     */
    @Test
    public void deleteUser(){
         User user = new User();
         user.setUid(11);
         //刪除
         session.delete(user);
    }

5   Transaction 事務

事務代表一次原子操作,任何持久層的操作都應該在事務下進行,即使是隻讀操作

開啓事務beginTransaction()

獲得事務getTransaction()

 

提交事務:commit()

回滾事務:rollback()

 

try{
   //開啓
   //session操作
   //提交
} catch(e){
   //回滾
}

 

6   工具類

public class H4Utils {
    // 會話工廠,整個程序只有一份。
    private static SessionFactory factory;
 
    static{
         //1 加載配置
         Configuration config = new Configuration().configure();
        
         //2 獲得工廠
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties())
                  .buildServiceRegistry();
         factory = config.buildSessionFactory(serviceRegistry);
 
//3 關閉虛擬機時,釋放SessionFactory
         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            
             @Override
             public void run() {
                  System.out.println("虛擬機關閉!釋放資源");
                  factory.close();
             }
         }));
    }
   
   
    /**
     * 獲得一個新的session
     * @return
     */
    public static Session openSession(){
         return factory.openSession();
    }
   
    /**
     * 獲得當前線程中綁定session
     * * 注意:必須配置<property name="hibernate.current_session_context_class">thread</property>
     * @return
     */
    public static Session getCurrentSession(){
         return factory.getCurrentSession();
    }
}


 

5      Session一級緩存

1   Session緩存介紹

Session接口的實現中包含一系列的Java集合,這些Java集合構成Session緩存,只要Session實例沒有結束生命週期,且沒有清理緩存,則存放在session緩存中的對象也不會結束生命週期。

Sesson緩存可以有效的減少Hibernate應用程序訪問數據庫的頻率。

@Test
    public void queryUser(){
         //查詢指定id的用戶
         User user = (User)session.get(User.class, 1);
         User use2 = (User)session.get(User.class, 1);
         System.out.println(user);
System.out.println(user2);
    }
 
上面代碼僅僅只發送一次sql語句,第二次獲取的時候,其實獲取的是session緩存中的數據

2   flush方法

 flush方法:使數據表中的記錄和Session緩存中的狀態保持一致,爲了保持一致,則可能會發送對應的sql語句。

 默認情況下,Transaction的commit方法中會先調用session的flush方法,再提交事務

 flush方法會發送一條update語句來更新數據庫數據,但不會提交事務(提交事務後數據庫數據纔會變動)

@Test
    public void testSessionFlush(){
         //查詢指定id的用戶
         User user = (User)session.get(User.class, 1);
         user.setUsername("cccc");
//手動刷新發送update語句(在transaction.commit方法之前加斷點,會看到打印)
         session.flush();
    }

 注意:這邊即使不寫session.flush()方法,打印結果仍然有update ……,原因在於transactioncommit操作會自動flush

關聯Hibernate源碼:關聯整個hibernate4.2.4 final就行

快捷鍵:ctrl+t 查看一個方法的具體實現


3   refresh方法

refresh方法會發送一條新的select語句到數據庫,更新當前數據信息

@Test
public void testSessionRefresh(){
	//查詢指定id的用戶
	User user = (User)session.get(User.class, 1);
	System.out.println(user);
	//refresh方法會發送一條新的select語句到數據庫,更新當前數據信息
	//例如在session.refresh方法上加斷點,再手動修改數據庫數據,此時會看到refresh方法之後打印的user也發生了變化
	session.refresh(user);	
	System.out.println(user);
}
注意:此處需要設施mysql事務的隔離級別
<!—在Hibernate.cfg.xml修改數據庫事務的隔離級別  
mysql默認事務隔離級別爲Repeatable Read,
其他數據庫一般爲Read Commited-->
<property name="hibernate.connection.isolation">2</property>


4   事務隔離級別 

  未授權讀取 默認值:1

也稱爲讀未提交(Read Uncommitted):允許髒讀取,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。


出現的問題:出現了髒數據

解決問題思路:禁止讀取未提交的數據

授權讀取 默認值:2

也稱爲讀提交(Read Committed):允許不可重複讀取,但不允許髒讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

出現的問題:我在讀取數據的時候別人修改了同一條數據,造成兩次訪問結果不一致

解決問題的思路:我在讀取指定數據的時候別人不可以修改該指定數據

可重複讀取 默認值:4

可重複讀取(Repeatable Read):禁止不可重複讀取連續兩次讀取,讀取的數據是一致的,同樣會造成查詢數據錯誤)和髒讀取,但是有時可能出現幻影數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

出現的問題:我和老婆並沒有同時操作同一條數據,但是因爲我新增了數據造成了別人讀取的步正確。

解決問題的思路:讓事務不能併發執行

序列化 默認值:8

序列化(Serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接着一個地執行,但不能併發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。



5   clear方法 

clear清理緩存:

@Test
    public void testSessionClear(){
         //查詢指定id的用戶
         User user = (User)session.get(User.class, 1);
         System.out.println(user);
         //清空緩存
         session.clear();
         User user2 = (User)session.get(User.class, 1);
         System.out.println(user2);
    }
 
//這邊會打印兩個select  …from 原因是session清空了

6 .Hibernate中持久化對象與session詳解

hibernate持久化狀態分類:臨時狀態、持久化狀態、託管狀態

臨時狀態

 Javanew命令開闢內存空間的java對象也就是普通的java對象,如果沒有變量引用它它將會被JVM收回。臨時對象在內存中是孤立存在的,它的意義是攜帶信息載體,不和數據庫中的數據由任何的關聯。

 通過Sessionsave()方法和saveOrUpdate()方法可以把一個臨時對象和數據庫相關聯,並把臨時對象攜帶的信息通過配置文件所做的映射插入數據庫中,這個臨時對象就成爲持久化對象。

持久化狀態

持久化對象在數據庫中有相應的記錄,持久化對象可以是剛被保存的,或者剛被加載的,但都是在相關聯的session聲明週期中保存這個狀態。如果是直接數據庫查詢所返回的數據對象,則這些對象和數據庫中的字段相關聯,具有相同的id,它們馬上變成持久化對象。如果一個臨時對象被持久化對象引用,也立馬變爲持久化對象。

如果使用delete()方法,持久化對象變爲臨時對象,並且刪除數據庫中相應的記錄,這個對象不再與數據庫有任何的聯繫。

持久化對象總是與SessionTransaction關聯在一起,在一個session中,對持久化對象的操作不會立即寫到數據庫,只有當Transaction(事務)結束時,才真正的對數據庫更新,從而完成持久化對象和數據庫的同步。

當一個session()執行close()、clear()、或evict()之後,持久化對象就變爲離線對象,這時對象的id雖然擁有數據庫的識別值,但已經不在Hibernate持久層的管理下,他和臨時對象基本上一樣的,只不過比臨時對象多了數據庫標識id。沒有任何變量引用時,jvm將其回收。

Hibernate使用OID來建立內存中的對應和數據庫中記錄的對應關係。對象的OID和數據庫表的主鍵對應。爲保證OID的唯一性,應該讓hibernate來爲OID賦值

 

脫管狀態

 Session關閉之後,與此Session關聯的持久化對象就變成爲脫管對象,可以繼續對這個對象進行修改,如果脫管對象被重新關聯到某個新的Session上,會在此轉成持久對象。

 脫管對象雖然擁有用戶的標識id,所以通過update()、saveOrUpdate()等方法,再次與持久層關聯。

 

1   Save方法

/**
     * save方法使一個臨時對象變爲持久化對象
     * save方法爲對象分配一個id
     * 在save方法之前設置的id無效
     * 持久化對象的id是不允許被修改的
     */
    @Test
    public void testSave(){
         User user = new User();
         user.setUsername("偉哥哥");
         user.setPassword("1234");
         System.out.println(user);
         //1.操作
         session.save(user);
         System.out.println(user);
    }
 
<!-- dynamic-insert:優化插入的sql語句-->
<class name="User" table="t_user" dynamic-insert="true">

2   Get和load方法

 get 通過id查詢,立刻發送sql語句。如果沒有 null

 load 通過id查詢,調動方法沒有發送sql語句,使用對象的時候才查詢數據庫。如果沒有拋異常

@Test
public void queryUser(){
     //查詢指定id的用戶
     User user = (User)session.get(User.class, 1);
     System.out.println(user);
}


   

 

public void queryUser(){
	//查詢指定id的用戶
        User user = (User)session.load(User.class, 1);
        session.close();
        System.out.println(user);
}
//上面代碼會拋懶加載異常,因爲session已經關了,而load方法再使用到user的時候會去查詢數據庫,沒有session而去查數據庫,報異常

 

3   update方法

/**
     * 1.更新一個持久化對象,無需顯示調用session.update()方法,因爲transaction.commit()方法會自動調用session的flush方法
     * 2.更新一個遊離對象,需要顯示調用session.update()方法,此時纔會更新數據庫,此時會把一個遊離對象轉換爲持久化對象
     */
    @Test
    public void testUpdate(){
         //持久化對象
         User user = (User)session.get(User.class, 1);
         System.out.println(user);
         user.setUsername("aaa");
         //此處無需調用session.update(user)方法,在調用transaction.commit()方法的時候會自動發送update更新語句
         transaction.commit();
        //關閉session會清空緩存,此時user變爲遊離對象
         session.close();
        
         //新開一個session,和原來的session已經沒關係了
         session = sessionFactory.openSession();
         //新開事務
         transaction = session.beginTransaction();
         //重新設置user的名字,如果此時不調用session.update(user),則默認的transaction.commit()方法不會自動發送update語句,原因是此時user爲遊離對象了
         user.setUsername("bbbb");
         session.update(user);
    }

4   saveOrUpdate方法

同時包含了save()與update()方法的功能


@Test
    public void testSaveOrUpdate(){
         User user = new User();
         user.setUsername("小小");
         user.setPassword("1234");
         //如果沒有id,則執行save方法
         //如果有id,但數據庫沒有和數據相關的記錄,則會拋出異常
         //如果有id,但數據庫有和數據相關的記錄,則執行update
         //user.setUid(100);
        
         session.saveOrUpdate(user);
    }

 

 

5   delete方法

@Test
    public void testDelete(){
         //刪除遊離對象,首先會將user變爲持久化對象
         User user = new User();
         user.setUid(12);
         session.delete(user);
        
         //刪除持久化對象
         User user2 = (User)session.get(User.class, 13);
         session.delete(user2);
         System.out.println(user2);
    }
 
問題:session.delete(user2)之後,打印的user2的id仍然存在,其實session.delete(user2)僅僅只是發送sql語句,並沒有提交事務`。
如果需要在session.delete(user2)之後就把user2的id設置爲null,則可以在hibernate.cfg.xml中配置
<!--刪除數據後設置oid爲null -->
<property name="use_identifier_rollback">true</property>


 

6   evict方法

從緩存中把指定的持久化對象移除

@Test
    public void testEvict(){
         User user1 = (User)session.get(User.class, 1);
         User user2 = (User)session.get(User.class, 12);
        
         user1.setUsername("AAA");
         user2.setUsername("BBB");
         //將user2從緩存中移除(user2不會更新數據庫)
         session.evict(user2);
    }
 
<!--update="false" :不允許更新該字段值 -->
<property name="username" type="java.lang.String" update="false">
     <column name="name" unique="true"  length="20"/>
</property>

7      配置c3p0數據源

1   導入libàoptionalàc3p0下的jar包

2   在hibernate.cfg.xml添加如下配置

hibernate.c3p0.max_size: 數據庫連接池的最大連接數

hibernate.c3p0.min_size: 數據庫連接池的最小連接數

hibernate.c3p0.timeout:   數據庫連接池中連接對象在多長時間沒有使用過後,就應該被銷燬

hibernate.c3p0.max_statements:  緩存 Statement 對象的數量

hibernate.c3p0.idle_test_period:  表示連接池檢測線程多長時間檢測一次池內的所有鏈接對象是否超時. 連接池本身不會把自己從連接池中移除,而是專門有一個線程按照一定的時間間隔來做這件事,這個線程通過比較連接對象最後一次被使用時間和當前時間的時間差來和 timeout 做對比,進而決定是否銷燬這個連接對象。

hibernate.c3p0.acquire_increment: 當數據庫連接池中的連接耗盡時, 同一時刻獲取多少個數據庫連接

 

//jdbc操作數據庫的時候statement讀取數據每次從數據庫讀取的數據條數

hibernate.jdbc.fetch_size:實質是調用 Statement.setFetchSize() 方法設定 JDBC 的 Statement 讀取數據的時候每次從數據庫中取出的記錄條數

²  例如一次查詢1萬條記錄,對於Oracle的JDBC驅動來說,是不會 1 次性把1萬條取出來的,而只會取出 fetchSize 條數,當結果集遍歷完了這些記錄以後,再去數據庫取 fetchSize 條數據。因此大大節省了無謂的內存消耗。Fetch Size設的越大,讀數據庫的次數越少,速度越快;Fetch Size越小,讀數據庫的次數越多,速度越慢。Oracle數據庫的JDBC驅動默認的Fetch Size = 10,是一個保守的設定,根據測試,當Fetch Size=50時,性能會提升1倍之多,當fetchSize=100,性能還能繼續提升20%,Fetch Size繼續增大,性能提升的就不顯著了。並不是所有的數據庫都支持Fetch Size特性,例如MySQL就不支持

//jdbc操作數據庫的時候statement刪除數據每次從數據庫刪除的數據條數

hibernate.jdbc.batch_size:設定對數據庫進行批量刪除,批量更新和批量插入的時候的批次大小,類似於設置緩衝區大小的意思。batchSize 越大,批量操作時向數據庫發送sql的次數越少,速度就越快。

²  測試結果是當Batch Size=0的時候,使用Hibernate對Oracle數據庫刪除1萬條記錄需要25秒,Batch Size = 50的時候,刪除僅僅需要5秒!Oracle數據庫batchSize=30 的時候比較合適。


<!--配置c3p0 -->
<!--c3p0最大連接數 -->
<property name="hibernate.c3p0.max_size">10</property>
<!--c3p0最小連接數 -->
<property name="hibernate.c3p0.min_size">5</property>
<!--c3p0中連接對象多久後沒有被使用應該被銷燬-->
<property name="hibernate.c3p0.timeout">2000</property>
<!--c3p0連接池檢測線程多久檢測一次池內所有鏈接對象是否超時-->
<property name="hibernate.c3p0.idle_test_period">2000</property>
<!--c3p0緩存statement數量-->
<property name="hibernate.c3p0.max_statements">10</property>
<!--c3p0連接池中連接耗盡時一次獲取的連接數-->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!--對數據庫進行批量查詢時,配置一次查詢獲取數據的條數-->
<property name="hibernate.jdbc.fetch_size">100</property>
<!--對數據庫進行批量刪除時,配置一次刪除刪除數據的條數-->
<property name="hibernate.jdbc.batch_size">30</property>
//測試當前session中的connection是否來自c3p0
@Test
    public void testDowork(){
         session.doWork(new Work() {
             @Override
             public void execute(Connection connection)throws SQLException {
                  // TODO Auto-generated method stub
                  System.out.println(connection);
             }
         });
    }


3   更多配置項

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章