舊調重彈Hibernate與Ibatis區別——深刻架構設計

對於一個粗學者而言一言概況就是:ibatis很是簡單易學,hibernate相對較複雜,門檻較高。 html

可是,hibernate對數據庫結構提供了較爲完整的封裝,hibernate的o/r mapping實現了pojo 和數據庫表之間的映射,以及sql 的自動生成和執行。程序員每每只需定義好了pojo 到數據庫表的映射關係,便可經過hibernate 提供的方法完成持久層操做。程序員甚至不須要對sql 的熟練掌握, hibernate/ojb 會根據制定的存儲邏輯,自動生成對應的sql 並調用jdbc 接口加以執行。 hibernate把數據庫和你隔離了,你不須要關注數據庫是mysql仍是oracle,hibernate來幫你生成查詢的sql。但問題也來了,若是你就要用某種數據庫特有的功能,或者你就要讓查詢的sql徹底符合你的心意,這就難了。java

由於hibernate則基本上能夠自動生成,偶爾會寫一些hql。一樣的需求,ibatis的工做量比hibernate要大不少。相似的,若是涉及到數據庫字段的修改,hibernate修改的地方不多,而ibatis要把那些sql mapping的地方一一修改。並且,從文檔的豐富性,產品的完善性,版本的開發速度都要強於ibatis。mysql

衆所周知,web開發,性能瓶頸在數據庫。好比12306,我以爲瓶頸仍是在數據庫。程序員

系統數據處理量巨大,性能要求極爲苛刻,這每每意味着咱們必須經過通過高度優化的sql語句(或存儲過程)才能達到系統性能設計指標。在這種狀況下ibatis會有更好的可控性和表現。 具體參考《Hibernate與Ibatis比較》——ibatis原理淺析web

  1. iBATIS沒有對你的數據庫模型和對象模型的設計作任何假設。不論你的應用中這兩個模型之間是多麼不匹配,iBATIS都能適用。更進一步,iBATIS沒有對你的企業級應用的架構作出任何假設。不論你對數據庫是根據業務功能縱向劃分,仍是按照技術橫向劃分,iBATIS都容許你高效地處理數據並將它們整合到你的面向對象的應用中去。sql

  2. iBATIS的某些特性使得它可以很是高效地處理大型數據集。iBATIS支持的行處理器(row handler)使得它可以批處理超大型記錄集,一次一條記錄。iBATIS也支持只獲取某個範圍內的結果,這就使得你能夠只獲取那些你當前亟需的數據。例如,假設你獲取了10,000條記錄,而你其實只須要其中的第500至600條,那你就能夠簡單的僅獲取這些記錄。iBATIS支持驅動提示使得執行這樣的操做很是高效。數據庫

  3. iBATIS容許你用多種方式創建從對象到數據庫的映射關係。一個企業級系統只以一種模式工做的狀況是很是少見的。許多企業級系統須要在白天執行事務性的工做,而在晚上執行批處理工做。iBATIS容許你將同一個類以多種方式映射,以保證每一種工做都能以最高效的方式執行。iBATIS一樣支持多種數據獲取策略。例如,你能夠選擇對某些數據進行懶加載,也能夠將一個複雜的對象圖只用一條聯合查詢SQL語句就同時加載完畢,從而避免嚴重的性能問題。apache

對於我我的來講,我首選ibatis。好比以前寫jsp,我就堅定不屑於JSTL,你能夠用intelliJ idea 智能提示快速開發。至於hql,shift……tomcat

兩者配置都差很少!無非就是:session

  • 編寫配置文檔 hibernate.cfg.xml或SqlMapConfig.xml:

  • 穿件對象—關係映射文件,

  • 編寫實體類(每個實體類都是和數據庫中的一張表是一一對應的的,設計遵循:javabean規範)

  • 生成對應實體類的映射文件並添加到1中的配置文檔

這裏科普下IBatis的詳細配置及使用狀況!節選自趙四的:iBatis開發的一個應用

下面是ibatis全局的文件:SqlMapConfig.xml:

  <?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMapConfig      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

  <!-- 配置數據庫鏈接 -->
  <transactionManager type="JDBC" commitRequired="false">
    <dataSource type="SIMPLE">
        <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>
        <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"/>
        <property name="JDBC.Username" value="root"/>
        <property name="JDBC.Password" value="jiangwei"/>     
        <property name="Pool.MaximumActiveConnections" value="10" />
        <property name="Pool.MaximumIdleConnections" value="5" />
        <property name="Pool.MaximumCheckoutTime" value="120000" />
        <property name="Pool.TimeToWait" value="500" />
        <property name="Pool.PingQuery" value="select 1 from account" />
        <property name="Pool.PingEnabled" value="false" />
        <property name="Pool.PingConnectionsOlderThan" value="1" />
        <property name="Pool.PingConnectionsNotUsedFor" value="1" />
    </dataSource>
  </transactionManager>
  <!-- 配置SQL查詢的配置文件的Account.xml -->
  <sqlMap resource="/Account.xml"/>
</sqlMapConfig>

對於上面的數據源配置的參數說明:

  • transactionManager節點定義了iBatis的事務管理器,提供三種方式

    JDBC、jta:分佈式數據庫、EXTERNAL:itbatis自己不作事務處理由外部進行處理

  • dataSource節點:從屬於transactionManager節點,用於設定ibatis運行期使用的DataSource屬性;

  • type屬性:type屬性指定了dataSource的實現模式,共三種模式,

    一、simple:ibatis提供的較小的鏈接池

    二、dbcp:是apache實現的鏈接池

    三、jndi:tomcate或weblogic提供的服務

  • JDBC.Driver:JDBC驅動;

  • JDBC.ConnectionURL:數據庫鏈接URL,若是用的是SQLServer JDBC Driver,須要在url後追加SelectMethod=Cursor以得到JDBC事務的多Statement支持;

  • JDBC.Username:數據庫用戶名;

  • JDBC.Password:數據庫用戶密碼;

  • Pool.MaximumActiveConnections:數據庫鏈接池可維持的最大容量;

  • Pool.MaximumIdleConnections:數據庫鏈接池中容許的掛起(idle)鏈接數;

  • Pool.MaximumCheckoutTime數據庫鏈接池中,鏈接被某個任務所容許佔用的最大時間,若是超過這個時間限定,鏈接將被強制收回,(毫秒);

  • Pool.TimeToWait:當線程試圖從鏈接池中獲取鏈接時,鏈接池中無可用鏈接可供使用,此時線程將進入等待狀態,直到池中出現空閒鏈接。此參數設定了線程所容許等待的最長時間,(毫秒);

  • Pool.PingQuery:數據庫鏈接狀態檢測語句。某些數據庫在某段時間持續處於空閒狀態時會將其斷開。而鏈接池管理器將經過此語句檢測池中鏈接是否可用,

  • 檢測語句應該是一個最簡化的無邏輯SQL。如「select 1 from user」,若是執行此語句成功,鏈接池管理器將認爲此鏈接處於可用狀態;

  • Pool.PingEnabled:是否容許檢測鏈接狀態;

  • Pool.PingConnectionsOlderThan:對持續鏈接時間超過設定值(毫秒)的鏈接進行檢測;

  • Pool.PingConnectionsNotUsedFor:對空閒超過設定值(毫秒)的鏈接進行檢測;

 

再看看Hibernate配置文件

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

<hibernate-configuration>
    <session-factory name="foo">
        <!-- 1. 配置數據庫信息 -->
        <!-- 方言(鏈接的數據庫類型) -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="connection.url">jdbc:mysql:///hibernate_20160926</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">yezi</property>
        <!-- 2. 其餘配置 -->
        <!-- 顯示生成的SQL語句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 3. 導入映射文件 -->
        <mapping resource="cn/itcast/a_helloworld/User.hbm.xml" />
    </session-factory>
</hibernate-configuration>

2.jpg

這裏只是參考對比下而已,沒有必要較真!

 

第二步,配置映射文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="Account">//命名空間

  <!-- 給Account實體類起一個別名 -->
  <typeAlias alias="Account" type="com.ibatis.demo.domain.Account"/>

  <!-- 將Account實體類中的屬性和mysql中的account表中的字段對應起來 -->
  <resultMap id="AccountResult" class="Account">
    <result property="id" column="_id"/>
    <result property="firstName" column="first_name"/>
    <result property="lastName" column="last_name"/>
    <result property="emailAddress" column="emall"/>
  </resultMap>

  <!-- 查詢account表中全部數據,其中id是這條查詢語句的id號,在代碼中用到,具備惟一性 -->
  <select id="selectAllAccounts" resultMap="AccountResult">
    select * from account
  </select>

  <!-- 經過id來查詢account表中的數據 -->
  <select id="selectAccountById" parameterClass="int" resultClass="Account">
    select
      id as _id,
      first_name as firstName,
      last_name as lastName,
      emall as emailAddress
    from account
    where _id = #id#
  </select>
   
  <!--插入語句-->
  <insert id="insertAccount" parameterClass="Account">
    insert into accout (
      _id,
      first_name,
      last_name,
      emall
    values (
      #id#, #firstName#, #lastName#, #emailAddress#
    )
  </insert>

  <!-- 更新語句 -->
  <update id="updateAccount" parameterClass="Account">
    update account set
      first_name = #firstName#,
      last_name = #lastName#,
      emall = #emailAddress#
    where
      _id = #id#
  </update>

  <!-- 刪除語句 -->
  <delete id="deleteAccountById" parameterClass="int">
    delete from account where _id = #id#
  </delete>

</sqlMap>

hibernate的:

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

<hibernate-mapping package="cn.itcast.a_helloworld">
    <class name="account" table="account">
        <id name="id" type="int" column="id">
            <generator class="native"/>
        </id>
        <property name="firstName" type="string" column="first_name" />
        <property name="lastName" type="string" column="last_name" />
        <property name="emailAddress" type="string" column="emall" />
    </class>
</hibernate-mapping>

 

建立實體類,其實就是javaBean,沒有什麼好說的。

再看看iBatis訪問數據的類:

package com.ibatis.demo.data;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.ibatis.common.resources.Resources;
import com.ibatis.demo.domain.Account;

import java.io.Reader;
import java.io.IOException;
import java.util.List;
import java.sql.SQLException;

public class IbaitsData {

  private static SqlMapClient sqlMapper;

  static {
    try {
      //讀取iBatis的配置文件:SqlMapConfig.xml
      Reader reader = Resources.getResourceAsReader("/SqlMapConfig.xml");
      sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
      reader.close(); 
    } catch (IOException e) {
      throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);
    }
  }

  //查詢account表中的全部記錄
  @SuppressWarnings("unchecked")
  public static List selectAllAccounts () throws SQLException {
    return sqlMapper.queryForList("selectAllAccounts");
  }

  //查詢account表中_id爲id的記錄
  public static Account selectAccountById  (int id) throws SQLException {
    return (Account) sqlMapper.queryForObject("selectAccountById", id);
  }

  //插入一條記錄
  public static void insertAccount (Account account) throws SQLException {
    sqlMapper.insert("insertAccount", account);
  }

  //更新一條記錄
  public static void updateAccount (Account account) throws SQLException {
    sqlMapper.update("updateAccount", account);
  }

  //刪除一條記錄
  public static void deleteAccount (int id) throws SQLException {
    sqlMapper.delete("deleteAccount", id);
  }

}

可是,到這裏就不想再對比了。我的以爲ibatis比hibernate簡單。畢竟寫slq就能夠了。

下面是Ibatis項目結構圖!

20131219115739890.png

參考文章:

Hibernate與Ibatis比較

【SSH進階之路】Hibernate基本原理(一)

【SSH進階之路】Hibernate搭建開發環境+簡單實例(二)

iBatis開發的一個應用

 Hibernate框架基礎——Hibernate入門

 

文章內容若有侵權,請告知以悉刪除,謝謝!

 

舊調重彈Hibernate與Ibatis區別--深刻架構設計 - java鏈接數據庫 - 周陸軍的我的網站

轉載註明來源。

相關文章
相關標籤/搜索