mybatis框架的搭建與mybatis-config.xml的配置


mybatis框架簡介

mybatis框架與Hibernate框架相比來說,專注於SQL語句,對SQL語句的編寫能力要求較高,同時對數據庫的事務也需要有好的理解,最主要的功能是mybatis框架可以將查詢到的結果集自動封裝成對象。

首先要進行一個環境的搭建:

  在這里我使用的IDE是eclipse

  使用的mybatis的版本是3.4.6的,同時也將源碼的jar包下載下來,還有必備的兩個DTD約束文件mybatis-3-mapper.dtd和mybatis-3-config.dtd

  使用的數據庫是MySQL

  由於mybatis也是相當於對JDBC的封裝,所以需要JDBC的jar包

  我也加入了一個log4j的日志支持

  

我們需要先將項目搭建起來

  

數據庫建表:

 

create table tbl_customer( id int primary key auto_increment, name varchar(20) , password varchar(200), zip varchar(20), address varchar(200), telephone varchar(15), email varchar(50) );
create table tbl_book( id int primary key auto_increment, name varchar(100), price double ); create table tbl_order( id int primary key auto_increment, cost double, orderDate date, customer_id int references tbl_customer(id) ); create table tbl_orderline( id int primary key auto_increment, num int, order_id int references tbl_order(id), book_id int references tbl_book(id) );
insert into tbl_book values(1,'JAVA核心技術',81); insert into tbl_book values(2,'UNIX技術手冊',21); insert into tbl_book values(3,'ORACLE9I參考手冊',108); insert into tbl_book values(4,'JSP設計(第三版)',59); insert into tbl_book values(5,'JAVA SERVLET 編程(第二版)',38); insert into tbl_book values(6,'XML 高級編程(第2版)',97); insert into tbl_book values(7,'精通STRUTS:基於MVC的JAVA WEB設計與開發',36); insert into tbl_book values(8,'精通HIBERNATE:JAVA對象持久化技術詳解',44); insert into tbl_book values(9,'SPRING IN ACTION中文版',29); insert into tbl_book values(10,'精通EJB 3.0',44);

 

 

 

逆向數據庫到模型:

 

 

我覺得,對於mybatis框架來說,最要緊的就是兩個配置文件,mybatis-config.xml和XxxxMapper.xml文件了,所以就從mybatis-config.xml開始說起吧。

首先呢是mybatis-config.xml文件的頭部:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 

可以看出這個xml文件引用了一個DTD文件的約束,所以說對框架來說是個有效的xml文件,這個兩個文件都可以在官網上下載,mybatis框架也是個開源的框架,這一點是很好的

注意:!!!這個xml文件由於dtd的約束使得標簽的順序唯一,標簽如果出現就必須按照嚴格的順序書寫(IDE是可以聯網關聯的,也可以自己設置)

我們來看這個xml文件的一個大致結構

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 

<configuration>
</configuration> 

configuration這個標簽中就是需要給框架配置的一系列標簽。

首先是properties標簽:

屬性配置元素properties可以將配置值寫死到mybatis-config.xml中,也可以具體到一個屬性文件中,並且使用屬性文件的key名作為占位符,在下述的配置中,我們將數據庫連接屬性配置到了application.properties文件中,並且為driver,URL等屬性使用了占位符。

在applications.properties文件中配置數據庫連接參數,如下所示:
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:XE
jdbc.username=xxx 
jdbc.password=xxx

<properties resource="application.properties"> 
    <!-- 這是設置優先級比較低的默認屬性 -->
    <property name="username" value="db_user" /> 
    <property name="password" value="verysecurepwd" /> 
</properties> 

這樣我們就可以在environment標簽中調用上述配置文件中的K-V值了:

envionment標簽是環境相關設置標簽,使用如下:

<!-- 這里的環境可以有多個,環境id不同,作用不同,如下,第一個environment作用是開發,第一個environment作用是生產 -->
  <environments default="development"> 
     <!-- 這里的id是指環境的id,常常寫為自己的作用 -->
    <environment id="development"> 
    <!-- 這個屬性是連接管理類型 一般有2個值可選-->
      <!-- JDBC 是需要應用程序自己管理事務 -->
      <!-- 例如,部署到ApacheTomcat的應用程序,需要應用程序自己管理事務。因為ApacheTomcat不會幫我們管理事務。 -->
      <!-- MANAGED 是讓服務器自動管理事務 像glassfish 服務器-->
      <transactionManager type="JDBC" /> 
      <!-- dataSource的類型type屬性可以配置成其內置類型之一,如UNPOOLED,POOLED,JNDI。 -->
      <dataSource type="POOLED"> 
<property name="driver" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> <environment id="production"> <transactionManager type="MANAGED" /> <dataSource type="JNDI"> <property name="data_source" value="java:comp/jdbc/MyBatisDemoDS" /> </dataSource> </environment> </environments>

typeAliases標簽:這個標簽是起個別名的作用

<!-- 這個屬性就是對pojo類起個別名 -->
<typeAliases> 
    <!-- 這里的意思是將 pojo.Student 類別名為 Student-->
    <typeAlias alias="Student" type="pojo.Student" /> 
    <!-- 這里的意思是將 pojo包下的所有類進行別名,比如pojo.Student 就會別名為student-->
    <!-- 優先級不高-->
    <package name="pojo" /> 
</typeAliases> 

接下來是一個比較復雜的問題:

類型處理器,這是一個在mybatis中相對復雜的問題,分為兩種情況,一是內建的類型處理器,再者是自己定義的類型

MyBatis對於以下的類型使用內建的類型處理器
所有的基本數據類型、基本類型的包裹類型
byte[]、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java枚舉類型等

如果是自己定義的類型,例子如下
假如在XxxxMapper.xml文件中配置一個insert插入語句,這里的phone是Student的一個內置對象,類型為PhoneNumber:

<insert id="insertStudent" parameter Type="Student"> insert into students(name,email,phone) values(#{name},#{email},#{phone}) </insert> 

為了讓MyBatis明白怎樣處理這個自定義的Java對象類型,如PhoneNumber,我們可以創建一個自定義的類型處理器,首先我們需要處理PhoneNumber類,加入一個getAsString方法

public class PhoneNumber{ private String countryCode; private String stateCode; private String number; public PhoneNumber(){} public PhoneNumber(String countryCode, String stateCode, String number){ this.countryCode = countryCode; this.stateCode = stateCode; this.number = number; } public PhoneNumber(String str){ if(str!=null){ String[] args = str.split("-"); this.countryCode = args[0]; this.stateCode = args[1]; this.number = args[2]; } } public String getAsString() { return countryCode + "-" + stateCode + "-" + number; } // Setters and getters 
}            

MyBatis提供了抽象類BaseTypeHandler<T> ,我們可以繼承此類創建自定義類型處理器。

public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>{ //遇到PhoneNumber參數的時候應該如何在ps中設置值
 @Override public void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType) throws SQLException { //這個方法就是調用了PhoneNumber類中的getAsString方法 //將這個對象以一個字符串的方式存入對應的表字段中
 ps.setString(i, parameter.getAsString()); } //查詢中遇到PhoneNumber類型的應該如何封裝(使用列名封裝)
 @Override public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException { //由上面的方法可以知道 //這個方法可以將以字符串的方式存入對應的表字段中的PhoneNumber對象取出來 //調用了PhoneNumber類中的一參構造器重新封裝為對象
            return new PhoneNumber(rs.getString(columnName)); } //查詢中遇到PhoneNumber類型的應該如何封裝(使用列的下標)
 @Override public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return new PhoneNumber(rs.getString(columnIndex)); } //CallableStatement使用中遇到了PhoneNumber類型的應該如何封裝
 @Override public PhoneNumber getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return new PhoneNumber(cs.getString(columnIndex)); } }

 

最后就需要在mybatis-config.xml文件中配置一下

  <typeHandlers> 
    <typeHandler handler="typehandlers.PhoneTypeHandler" /> 
    <!--這個標簽貌似也是個別名的作用,不過我沒用過-->
    <package name="typehandlers" /> 
  </typeHandlers> 

接下來是mappers元素,主要用於 SQL映射

SQLMapper文件中主要是對SQL語句的映射,表明這個sql語句對應哪個方法的調用。我們需要在mybatis-config.xml文件中配置 SQLMapper文件的位置。

resource屬性用來指定在classpath中的mapper文件。
url屬性用來通過完全文件系統路徑或者web URL地址來指向mapper文件
class屬性用來指向一個mapper接口
package屬性用來指向可以找到Mapper接口的包名 

其實在項目中常常只要一個屬性就足夠定位了

  <mappers> 
    <mapper resource="mappers/StudentMapper.xml" /> 
    <mapper url="file:///D:/mybatisdemo/app/mappers/StudentMapper.xml" /> 
    <mapper class="mappers.StudentMapper" /> 
    <package name="com.mappers" /> 
  </mappers> 

最后是settings元素: 全局參數設置

settings元素有好多的參數設置

注意:大多數情況下,【這些參數使用它們的默認值即可】

<settings>
          <!-- 這個配置使全局的映射文件啟用或禁用緩存 -->
          <setting name="cacheEnabled" value="true" />
          <!-- 全局啟用或禁用延遲加載。當禁用時,所有關聯對象都會即時加載 -->
          <setting name="lazyLoadingEnabled" value="true" />
          <!-- 允許或不允許多種結果集從一個單獨的語句中返回(需要適合的驅動) -->
          <setting name="multipleResultSetsEnabled" value="true" /> 
          <!-- 使用列標簽代替列名。不同的驅動在這方便表現不同。參考驅動文檔或充分測試兩種方法來決定所使用的驅動 -->
          <setting name="useColumnLabel" value="true" /> 
          <!-- 允許JDBC支持生成的鍵。需要適合的驅動。 -->
          <setting name="useGeneratedKeys" value="false" /> 
          <!-- 指定MyBatis如何自動映射列到字段/屬性。PARTIAL只會自動映射簡單、沒有嵌套的結果。FULL會自動映射任意復雜的結果(嵌套的或其他情況) -->
          <setting name="autoMappingBehavior" value="PARTIAL" />
          <!-- 配置默認的執行器。SIMPLE執行器沒有什么特別之處。REUSE執行器重用預處理語句。BATCH執行器重用語句和批量更新 -->
          <setting name="defaultExecutorType" value="SIMPLE" /> 
          <!-- 設置超時時間,它決定驅動等待一個數據庫響應的時間 -->
          <setting name="defaultStatementTimeout" value="25000" />         
          <!-- 允許在嵌套語句中使用分頁(RowBounds)默認false -->
          <setting name="safeRowBoundsEnabled" value="false" /> 
          <!-- 是否開啟自動駝峰命名規則(camel case)映射,即從經典數據庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的類似映射。默認false -->
          <setting name="mapUnderscoreToCamelCase" value="false" /> 
          <!-- MyBatis 利用本地緩存機制(Local Cache)防止循環引用(circular references)和加速重復嵌套查詢。 默認值為 SESSION,這種情況下會緩存一個會話中執行的所有查詢。 若設置值為 STATEMENT,本地會話僅用在語句執行上,對相同 SqlSession 的不同調用將不會共享數據。 -->
          <setting name="localCacheScope" value="SESSION" /> 
          <!-- 當沒有為參數提供特定的 JDBC 類型時,為空值指定 JDBC 類型。 某些驅動需要指定列的 JDBC 類型,多數情況直接用一般類型即可,比如 NULL、VARCHAR 或 OTHER。 -->
          <setting name="jdbcTypeForNull" value="NULL" />
          <!-- 指定對象的哪個方法觸發一次延遲加載。 -->
          <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode ,toString" /> 
          <!-- CGLIB | JAVASSIST 默認JAVASSIST(MyBatis 3.3 or above) -->
          <!-- 指定 Mybatis 創建具有延遲加載能力的對象所用到的代理工具。 -->
          <setting name="proxyFactory" value="JAVASSIST" /> 
          <!-- 當啟用時,對任意延遲屬性的調用會使帶有延遲加載屬性的對象完整加載;反之,每種屬性將會按需加載。 -->
          <setting name="aggressiveLazyLoading" value="true" />           
          <!-- 指定 MyBatis 所用日志的具體實現,未指定時將自動查找。 -->
          <setting name="logImpl" value="LOG4J " /> 
          <!-- 指定 MyBatis 增加到日志名稱的前綴。值可以是任意字符串 -->
          <setting name="logPrefix" value="LOG4J " /> 
          <!-- 指定當結果集中值為 null 的時候是否調用映射對象的 setter(map 對象時為 put)方法,這對於有 Map.keySet() 依賴或 null 值初始化的時候是有用的。注意基本類型(int、boolean等)是不能設置成 null 的。 默認false-->
          <setting name="callSettersOnNulls" value="false " /> 
</settings> 

拿其中的一個我認為最常用的,比如 <setting name="jdbcTypeForNull" value="NULL" /> 這個設置就可以有效的幫助我們避免“1111”錯誤

這個配置是說如果當插入的值為空時給一個NULL屬性,就避免了“1111”錯誤,比如我在將一個對象插入到表中的時候,一個屬性沒有值,在有些環境中數據庫無法解析這個空的指向,就會報出“1111”錯誤,如果設置了這個屬性這個空的指向就可以設為空

在package org.apache.ibatis.type包中中有一個枚舉JdbcType,定義了一系列類型,但是一個數據庫不可能完全支持這些類型,源碼如下:

package org.apache.ibatis.type; import java.sql.Types; import java.util.HashMap; import java.util.Map; /** * @author Clinton Begin */
public enum JdbcType { /* * This is added to enable basic support for the * ARRAY data type - but a custom type handler is still required */ ARRAY(Types.ARRAY), BIT(Types.BIT), TINYINT(Types.TINYINT), SMALLINT(Types.SMALLINT), INTEGER(Types.INTEGER), BIGINT(Types.BIGINT), FLOAT(Types.FLOAT), REAL(Types.REAL), DOUBLE(Types.DOUBLE), NUMERIC(Types.NUMERIC), DECIMAL(Types.DECIMAL), CHAR(Types.CHAR), VARCHAR(Types.VARCHAR), LONGVARCHAR(Types.LONGVARCHAR), DATE(Types.DATE), TIME(Types.TIME), TIMESTAMP(Types.TIMESTAMP), BINARY(Types.BINARY), VARBINARY(Types.VARBINARY), LONGVARBINARY(Types.LONGVARBINARY), NULL(Types.NULL), OTHER(Types.OTHER), BLOB(Types.BLOB), CLOB(Types.CLOB), BOOLEAN(Types.BOOLEAN), CURSOR(-10), // Oracle
UNDEFINED(Integer.MIN_VALUE + 1000), NVARCHAR(Types.NVARCHAR), // JDK6
NCHAR(Types.NCHAR), // JDK6
NCLOB(Types.NCLOB), // JDK6
STRUCT(Types.STRUCT), JAVA_OBJECT(Types.JAVA_OBJECT), DISTINCT(Types.DISTINCT), REF(Types.REF), DATALINK(Types.DATALINK), ROWID(Types.ROWID), // JDK6
LONGNVARCHAR(Types.LONGNVARCHAR), // JDK6
SQLXML(Types.SQLXML), // JDK6
DATETIMEOFFSET(-155); // SQL Server 2008

public final int TYPE_CODE; private static Map<Integer,JdbcType> codeLookup = new HashMap<Integer,JdbcType>(); static { for (JdbcType type : JdbcType.values()) { codeLookup.put(type.TYPE_CODE, type); } } JdbcType(int code) { this.TYPE_CODE = code; } public static JdbcType forCode(int code) { return codeLookup.get(code); } }

常用的標簽就這些了,這些標簽的順序為

properties,settings,typeAliases,typeHandlers,environments,mappers

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM