Mybatis入門以及配置檔案解析
一 mybatis入門
1.1 mybatis是什麼 MyBatis是一個簡化和實現了 Java 資料持久化層(persistence layer)的開源框架,它抽象了大量的JDBC冗餘程式碼,並提供了一個簡單易用的API和資料庫互動。 MyBatis的前身是iBATIS,iBATIS於2002年由ClintonBegin建立。MyBatis3是iBATIS的全新設計,支援註解和Mapper。 MyBatis流行的主要原因在於它的簡單性和易使用性。在Java應用程式中,資料持久化層涉及到的工作有:將從資料庫查詢到的資料生成所需要的Java物件;將Java物件中的資料通SQL持久化到資料庫中。 MyBatis通過抽象底層的JDBC程式碼,自動化SQL結果集產生Java物件、Java物件的資料持久化資料庫中的過程使得對SQL的使用變得容易。 1.2 Git 是一個免費開源的分散式版本控制系統,被用於高速有效地處理大大小小專案中所有檔案,在軟體開發中使用的其他版本控制軟體類似與SVN、VSS、CVS等等. 1.3 作為一個分散式的版本控制系統,在Git中並不存在主庫這樣的概念,每一份複製出的庫都可以獨立使用,任何兩個庫之間的不一致之處都可以進行合併。github以託管各種git庫,並提供一個web介面,可以說是一款易於使用的git圖形客戶端。我們熟知的spring、struts、Hibernate等框架的原始碼在github上面都可以找到其原始碼 1.4 iBATIS一詞來源於internet和abatis的組合,是一個在2002年發起的開放原始碼專案。於2010年6月16號被谷歌託管,改名為MyBatis。 ibatis的官網 http://ibatis.apache.org/ 進去官網會看到下面提示: apache ibatis is retired at the apache software foundation (2010/06/16) the original project team has moved to mybatis hosted at google code. see http://www.mybatis.org/ for more. 然而http://www.mybatis.org/這個地址一直處於打不開狀態... 但是我們最終是可以在github中找到mybatis的相關下載的: mybatis在github中的地址 https://github.com/mybatis/mybatis-3 最新版本的mybatis的下載地址 https://github.com/mybatis/mybatis-3/releases doc文件 http://www.mybatis.org/mybatis-3/ 1.5 當前有很多Java實現的持久化框架,而MyBatis流行起來有以下原因: 1.5.1 它消除了大量的JDBC冗餘程式碼 Java通過JDBC的API來操作關係型資料庫,但是JDBC是一個非常底層的API,我們需要書寫大量的程式碼來完成對資料庫的操作。例如一個插入操作(參考之前學習JDBC時候的程式碼例項) 但是使用mybatis來完成相同的插入操作要簡單方便靈活的多: 第一步:在SQLMapper對映配置檔案中配置SQL語句,假定為StudentMapper.xml <insert id="insertStudent" parameterType="Student"> INSERT INTO STUDENTS(ID,NAME,EMAIL) VALUES(#{id},#{name},#{email}) </insert> 第二步:建立一個StudentMapper介面 public interface StudentMapper{ void insertStudent(Student student); } 第三步:編寫java程式碼完成插入操作: SqlSession session = getSqlSessionFactory().openSession(); StudentMapper mapper = session.getMapper(StudentMapper.class); mapper.insertStudent(student); 特別之處的是,MyBatis還提供了其他的一些特性來簡化持久化邏輯的實現 它支援複雜的SQL結果集資料對映到巢狀的物件結構 它支援一對一和一對多的結果集和Java物件的對映 它支援根據輸入的資料構建動態的SQL語句 1.5.2 它有低的學習曲線 MyBatis能夠流行的首要原因之一在於它學習和使用起來非常簡單,它取決於你Java和 SQL方面的知識。如果開發人員很熟悉Java和SQL,他們會發現MyBatis入門非常簡單。 1.5.3 它能很好地與傳統資料庫協同工作 有時我們可能需要用不正規形式與傳統資料庫協同工作,使用成熟的ORM框架(例如大家熟知的Hibernate)有可能、但是很難跟傳統資料庫很好地協同工作,因為他們嘗試將Java物件靜態地對映到資料庫的表上.而MyBatis是將查詢的結果與Java物件對映起來,這使得MyBatis可以很好地與傳統資料庫協同工作。你可以根據面相物件的模型建立Java域物件,執行傳統資料庫的查詢,然後將結果對映到對應的Java物件上。 1.5.4 它可以接受SQL語句 成熟的ORM框架鼓勵使用實體物件和在其底層自動產生SQL語句。由於這種的SQL生成方式,我們有可能不能夠利用到資料庫的一些特有的特性。Hibernate允許執行本地SQL,但是這樣會打破持久層和資料庫獨立的原則。MyBatis框架接受SQL語句,而不是將其對開發人員隱藏起來。由於MyBatis不會產生任何的SQL語句,所以開發人員就要準備SQL語句,這樣就可以充分利用資料庫特有的特性並且可以準備自定義的查詢。另外,MyBatis 對儲存過程也提供了支援。 1.5.5 它提供了與Spring框架的整合支援 MyBatis提供了與流行的依賴注入框架Spring的開包即用的整合支援,這將進一步簡化MyBatis的使用 1.5.6 它提供了與第三方快取類庫的整合支援 MyBatis有內建的SqlSession級別的快取機制,用於快取Select語句查詢出來的結果。除此之外,MyBatis提供了與多種第三方快取類庫的整合支援,如EHCache,OSCache,Hazelcast等。 1.5.7 它引入了更好的效能 效能問題是關乎軟體應用成功與否的關鍵因素之一。為了達到更好的效能,需要考慮很多事情,而對很多應用而言,資料持久化層是整個系統性能的關鍵。MyBatis支援資料庫連線池,消除了為每一個請求建立一個數據庫連線的開銷,MyBatis提供了內建的快取機制,在SqlSession級別提供了對SQL查詢結果的快取。即:如果你呼叫了相同的select查詢,MyBatis 會將放在快取的結果返回,而不會去再查詢資料庫。MyBatis框架並沒有大量地使用代理機制,因此對於其他的過度地使用代理的ORM框架而言,MyBatis可以獲得更好的效能. 1.6 mybatis的jar包 mybatis的核心包只有一個mybatis-3.x.0.jar,另外還有一些【可選】的依賴包(日誌、代理等所需要的),在下載的壓縮包中可以找到. 1.7 mybatis框架中一般需要倆種檔案: 第一種:mybatis的配置檔案: mybatis-config.xml,其中包括資料庫連線資訊,類型別名等等 特點: 名字一般是固定的 位置是src下面 示例: <?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> <typeAliases> <typeAlias alias="Student" type="com.ijavac.pojo.Student" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <!-- <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test" /> --> <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" /> <property name="username" value="test" /> <property name="password" value="test" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/ijavac/pojo/StudentMapper.xml" /> </mappers> </configuration> 第二種:mybatis的對映檔案:XxxxxMapper.xml,這個xml檔案中包括Xxxx類所對應的資料庫表的各種增刪改查sql語句 特點: 名字一般為XxxxMapper.xml,Xxxx是對應類的名字 位置不固定,一般放到一個專門的package裡面 例項: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ijavac.pojo.StudentMapper"> <resultMap type="Student" id="StudentResult"> <id property="id" column="id" /> <result property="name" column="name" /> <result property="email" column="email" /> </resultMap> <select id="findAllStudents" resultMap="StudentResult"> SELECT * FROM STUDENTS </select> <select id="findStudentById" parameterType="int" resultType="Student"> SELECT ID AS STUDID, NAME, EMAIL FROM STUDENTS WHERE ID=#{Id} </select> <insert id="insertStudent" parameterType="Student"> INSERT INTO STUDENTS(ID,NAME,EMAIL) VALUES(#{id },#{name},#{email}) </insert> </mapper> 1.8 mybatis中的對映介面XxxxMapper.java(對XxxxMapper.xml中的sql語句進行對映) mybatis中除了必須的jar包、各種xml配置檔案之外,一般還需要有呼叫sql語句執行的介面XxxxMapper.java 示例: public interface StudentMapper{ List<Student> findAllStudents(); Student findStudentById(Integer id); void insertStudent(Student student); } 注意:介面中的方法的名字和XML檔案定義的SQL對映語句的名稱要相同 同時我們不需要去實現該介面,因為mybatis中提供了相應的方式在執行期間動態生成該介面的實現類物件(動態代理技術,spring框架中會詳細講解動態代理). 1.9 mybatis中的SqlSession介面和sqlSessionFactory介面 SqlSession介面的實現類物件是mybatis中最重要的一個物件,我們可以使用該物件動態獲得XxxxMapper.java介面的實現類物件,然後就可以呼叫到XxxxMapper.java介面中方法所對映的sql語句(在xml檔案中配置的sql語句)。 sqlSessionFactory介面的實現類物件是一個工廠物件,專門負責來產生SqlSession物件的 例如: InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); //第一種執行sql語句的方式 通過XxxxMapper介面的實現類物件來呼叫 //動態獲得XxxxMapper介面的實現類 StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); studentMapper.insertStudent(new Student(1,"tom","
[email protected]")); //第二種執行sql語句的方式 執行呼叫XxxxMapper.xml中寫好的sql語句 //也可以【不通過】Mapper介面執行對映的SQL //然而,使用 Mapper介面是最佳實踐 //sqlSession.selectOne("com.ijavac.pojo.StudentMapper.findStudentById",1); 1.10 編寫一個簡單的mybatis進行插入資料的例項 1.10.1 資料庫建表 dob=Date of Birth CREATE TABLE STUDENTS ( stu_id number PRIMARY KEY, name varchar2(50) , email varchar2(50) , dob date ); 1.10.2 新建一個專案,建立好相應的package及class package com.ijavac.pojo; import java.util.Date; public class Student { private Integer studId; private String name; private String email; private Date dob; get/set } 1.10.3 專案中引入mybatis的核心包以及可選的依賴包 必須的包 mybatis-3.3.0.jar ojdbc14.jar 可選的包 junit-4.7.jar log4j-1.2.17.jar 1.10.4 mybatis中的配置檔案和對映檔案分別引入到專案中 src下面的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"> <configuration> <typeAliases> <typeAlias type="com.ijavac.pojo.Student" alias="Student" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" /> <property name="username" value="test" /> <property name="password" value="test" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/ijavac/mappers/StudentMapper.xml"/> </mappers> </configuration> com.ijavac.mappers包下面的StudentMapper.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- com.ijavac.mappers.StudentMapper是我們定義介面的全限定名字 這樣就可以使用介面呼叫對映的SQL語句了 這個名字一定要和介面對應上--> <mapper namespace="com.ijavac.mappers.StudentMapper"> //和定義的介面路徑一致 <resultMap type="Student" id="StudentResult"> <id property="studId" column="stud_id" /> <result property="name" column="name" /> <result property="email" column="email" /> <result property="dob" column="dob" /> </resultMap> <select id="findAllStudents" resultMap="StudentResult"> SELECT * FROM STUDENTS </select> <!-- 列名和屬性名字不一致可以給查詢的列起一個別名 --> <select id="findStudentById" parameterType="int" resultType="Student"> SELECT STUD_ID AS STUDID,NAME,EMAIL,DOB FROM STUDENTS WHERE STUD_ID=#{id} </select> <insert id="insertStudent" parameterType="Student"> INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(#{studId},#{name},#{email},#{dob}) </insert> </mapper> 1.10.5 配置log4j.properties檔案中的日誌輸出: 位置src下面 內容: log4j.rootLogger=DEBUG, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d [%-5p] %c - %m%n #show sql log4j.logger.java.sql.ResultSet=INFO log4j.logger.org.apache=INFO log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG 1.10.6 com.ijavac.mappers包下面新建一個介面StudentMapper.java,用來對應xml檔案中的sql語句(對映),從而方便我們呼叫 package com.ijavac.mappers; import java.util.List; import com.ijavac.pojo.Student; //建立對映器Mapper介面StudentMapper //方法名和StudentMapper.xml中定義的SQL對映定義名相同 //這個其實就是dao層介面(資料訪問層,負責和資料庫進行互動) public interface StudentMapper { List<Student> findAllStudents(); Student findStudentById(Integer id); void insertStudent(Student student); } 1.10.7 建立一個測試類StudentMapperTest.java package test; import java.io.InputStream; import java.util.Date; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import com.ijavac.mappers.StudentMapper; import com.ijavac.pojo.Student; public class StudentMapperTest { @Test public void testInsert(){ try { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); Student s = new Student(1,"tom","[email protected]",new Date()); studentMapper.insertStudent(s); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } } } 1.10.8 執行成功後會在控制檯中看到log4j日誌輸出的這個程式執行的相關資訊 1.10.9 對mybatis的一些基本封裝 每次讀取配置檔案,產生一個工廠物件SqlSessionFactory,然後再生成出SqlSession物件,這個過程雖然並不複雜,但是也都是一些重複的程式碼流程,所以我們可以對其進行一個簡單的封裝: package com.ijavac.utils; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisSqlSessionFactory { private static SqlSessionFactory sqlSessionFactory; public static SqlSessionFactory getSqlSessionFactory(){ if(sqlSessionFactory == null){ InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e.getCause()); } } return sqlSessionFactory; } public static SqlSession openSession() { return getSqlSessionFactory(). openSession(false); } public static SqlSession openSession(boolean autoCommit) { return getSqlSessionFactory().openSession(autoCommit); } } 之後每次使用的時候只需要呼叫該類中的靜態方法openSession即可 上面的程式碼可簡寫為: //注意事務是自動提交還是手動提交 MyBatisSqlSessionFactory.openSession().getMapper(StudentMapper.class).insertStudent(s);
二 mybatis配置詳解
MyBatis最關鍵的組成部分是SqlSessionFactory,我們可以從中獲取SqlSession, 並執行對映的SQL語句。SqlSessionFactory物件可以通過基於XML的配置資訊或者JavaAPI建立。
2.1 使用xml配置Mybatis
構建SqlSessionFactory最常見的方式是基於XML配置。下面的 mybatis-config.xml展示了一個典型的MyBatis配置檔案的樣子:
<?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>
<properties resource="application.properties">
<property name="username" value="db_user" />
<property name="password" value="verysecurepwd" />
</properties>
<settings>
<setting name="cacheEnabled" value="true" />
</settings>
<typeAliases>
<typeAlias alias="Student" type="com.ijavac.pojo.Student" />
<package name="com.ijavac.pojo" />
</typeAliases>
<typeHandlers>
<typeHandler handler="com.mybatis3.typehandlers.PhoneTypeHandler" />
<package name="com.ijavac.typehandlers" />
</typeHandlers>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<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>
<mappers>
<mapper resource="com/ijavac/mappers/StudentMapper.xml" />
<mapper url="file:///D:/mybatisdemo/mappers/StudentMapper.xml" />
<mapper class="com.ijavac.mappers.StudentMapper" />
</mappers>
</configuration>
2.1.1 environments元素
environments是配置mybatis當前工作的資料庫環境的地方
MyBatis支援配置多個dataSource環境,可以將應用部署到不同的環境上,如DEV(開發環境),TEST(測試環境),QA(質量評估環境),UAT(使用者驗收環境),PRODUCTION(生產環境),可以通過將預設environments值設定成想要的environment的id值。
有時候,我們可能需要在相同的應用下使用多個數據庫,比如我們可能有shoppingcart資料庫來儲存所有的訂單明細;使用reports資料庫儲存訂單明細的合計,用作報告。(也就是如果系統在執行期間如果有切換資料庫環境的需求,mybatis中也可以很輕鬆的實現).
如果你的應用需要連線多個數據庫,你需要將每個資料庫配置成獨立的環境,並且為每一個數據庫建立一個SqlSessionFactory
例如:
<environments default="shoppingcart">
<environment id="shoppingcart">
<transactionManager type="MANAGED" />
<dataSource type="JNDI">
<property name="data_source" value="java:comp/jdbc/ShoppingcartDS" />
</dataSource>
</environment>
<environment id="reports">
<transaction Managertype="MANAGED" />
<dataSource type="JNDI">
<property name="data_source" value="java:comp/jdbc/ReportsDS" />
</dataSource>
</environment>
</environments>
我們可以為以上每個環境建立一個SqlSessionFactory
java程式碼:
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//預設的環境
defaultSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//統計明細的環境
cartSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "shoppingcart");
//統計報表的環境
reportSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "reports");
注意:對於environments,我們可以在其中配置多個environment子元素,同時還需要在environment中配置dataSource和transactionManager元素。
2.1.2 dataSource元素
dataSource表示的是資料來源:至少會包括該連線資料庫的各種資訊
<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>
dataSource的型別type屬性可以配置成其內建型別之一,如UNPOOLED,POOLED,JNDI。
如果將型別設定成UNPOOLED,MyBatis會為每一個數據庫操作建立一個新的連線,使用完了並關閉它,該方式適用於只有小規模數量併發使用者的簡單應用程式上。
如果將屬性設定成POOLED,MyBatis會建立一個數據庫連線池,連線池中的一個連線將會被用作資料庫操作。一旦資料庫操作完成,MyBatis會將此連線返回給連線池。在開發或測試環境中,經常使用此種方式。
如果將型別設定成JNDI(Java Naming and Directory Interface , Java命名和目錄介面, 是SUN公司提供的一種標準的Java命名系統介面),MyBatis從在應用伺服器向配置好的JNDI資料來源dataSource獲取資料庫連線。在生產環境中,優先考慮這種方式。
2.1.3 transactionManager元素 :事務管理器
MyBatis支援兩種型別的事務管理器:JDBC 和 MANAGED.
JDBC事務管理器的使用,是在【jdbc程式】負責管理資料庫連線的生命週期(提交、回退等等)的時候。如果將TransactionManager 屬性設定成JDBC,MyBatis內部將使用JdbcTransactionFactory類建立TransactionManager。例如,部署到ApacheTomcat的應用程式,需要應用程式自己管理事務。
MANAGED 事務管理器的使用,是在【應用伺服器】負責管理資料庫連線生命週期的時候。如果將TransactionManager屬性設定成MANAGED時,MyBatis內部使用ManagedTransactionFactory 類建立事務管理器TransactionManager。例如,當一個Java EE的應用程式部署在類似JBoss,WebLogic,GlassFish應用伺服器上時,它們會使用EJB進行應用伺服器的事務管理能力。在這些管理環境中,你可以使用MANAGED事務管理器。
注:Managed 是託管的意思,即我們編寫的應用程式本身不去管理事務,而是把事務管理交給應用所在的伺服器進行管理。
2.1.4 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=test
jdbc.password=test
在mybatis-config.xml檔案中,為屬性使用application.properties檔案中定義的佔位符:
<!-- 讀取application.properties檔案中的資料key-value的形式 -->
<properties resource="application.properties">
<!-- 注意:是applications.properties檔案中的值優先順序高 -->
<property name="jdbc.username" value="ijavac" />
<property name="jdbc.password" value="ijavac" />
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<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>
</environments>
2.1.5 typeAliases元素: 類型別名
在SQLMapper配置檔案中,對於resultType和parameterType屬性值,我們需要使用JavaBean 的完全限定名。
例如:
<select id="findStudentById" parameterType="int"
resultType="com.ijavac.pojo.Student">
SELECT STUD_ID AS ID, NAME, EMAIL, DOB
FROM STUDENTS WHERE STUD_ID=#{Id}
</select>
<update id="updateStudent" parameterType="com.ijavac.pojo.Student">
UPDATE STUDENTS
SET NAME=#{name}, EMAIL=#{email}, DOB=#{dob}
WHERE STUD_ID=#{id}
</update>
注:parameterType表示將來呼叫這個sql語句的時候所傳的引數的型別(引數值或者引數物件裡面的屬性值 用來替換sql語句中的佔位符)
resultType表示將來呼叫這個sql語句的時候所返回的結果的型別(方便mybatis給我們自動封裝結果集)
這裡我們為resultType和parameterType屬性值設定為Student型別的完全限定名:com.ijavac.com.Student
我們可以為完全限定名取一個別名(alias),然後就可以在需要使用完全限定名的地方使用別名,而不是到處使用完全限定名。如下例子所示,為完全限定名起一個別名:
<type Aliases>
<type Alias alias="Student" type="com.ijavac.pojo.Student" />
<type Alias alias="Teacher" type="com.ijavac.pojo.Teacher" />
</type Aliases>
然後在SQLMapper對映檔案中, 如下使用Student的別名:
<select id="findStudentById" parameterType="int" resultType="Student">
SELECT STUD_ID AS ID, NAME, EMAIL, DOB
FROM STUDENTS WHERE STUD_ID=#{id}
</select>
<update id="updateStudent" parameterType="Student">
UPDATE STUDENTS
SET NAME=#{name}, EMAIL=#{email}, DOB=#{dob}
WHERE STUD_ID=#{id}
</update>
你可以不用為每一個JavaBean單獨定義別名,你可以為配置出需要取別名的類的所在的包(package),MyBatis會自動掃描包內定義的類,然後分別為每個類註冊一個小寫字母開頭的簡單類名形式的別名。如下所示:
<type Aliases>
<package name="com.ijavac.pojo" />
</type Aliases>
如果Student.java和 Teacher.java 定義在com.ijavac.pojo包中,則 com.ijavac.pojo.Student的別名會被註冊為student。而com.ijavac.pojo.Teacher別名將會被註冊為teacher
還有另外一種方式為JavaBeans起別名,使用註解 @Alias:
@Alias("stu")
public class Student{
....
}
@Alias註解將會覆蓋配置檔案中的<typeAliases>定義。
2.1.6 typeHandlers元素: 型別處理器
當MyBatis將一個Java物件作為輸入引數執行INSERT語句操作時,它會建立一個PreparedStatement物件,並且使用setXXX()方法對佔位符設定相應的引數值 。這裡,XXX可以是Int,String,Date 等 Java物件屬性型別的任意一個。示例如下:
<insert id="insert Student" parameter Type="Student">
INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB)
VALUES(#{stud Id},#{name},#{email},#{dob})
</insert>
為執行這個語句,MyBatis將採取以下一系列動作:
建立一個有佔位符的PreparedStatement介面,如下:
Prepared Statement ps = connection.prepare Statement
("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(?,?,?,?)");
檢查Student物件的屬性studId的型別,然後使用合適setXXX方法去設定引數值。這裡studId是integer型別,所以會使用setInt()方法:ps.setInt(1,student.getStudId());
類似地,對於name和email屬性都是String型別MyBatis使用setString()方法設定引數。
至於dob屬性, MyBatis會使用setDate()方法設定dob處佔位符位置的值。
MyBaits會將java.util.Date型別轉換為java.sql.Timestamp並設值:
ps.setTimestamp(4, new Timestamp((student.getDob()).getTime()));
但MyBatis是怎麼知道對於Integer型別屬性使用setInt()和String型別屬性使用setString()方法呢?其實MyBatis是通過使用型別處理器typeHandlers來決定這麼做的。
MyBatis對於以下的型別使用內建的型別處理器:所有的基本資料型別、基本型別的包裹型別、 byte[]、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java列舉型別等。所以當MyBatis發現屬性的型別屬於上述型別,他會使用對應的型別處理器將值設定到PreparedStatement中,同樣地,當SQL結果集封裝成java類物件的時候,也有類似的過程。
那如果有一個自定義的型別,怎麼儲存儲存到資料庫呢?示例如下:假設表STUDENTS 有一個 PHONE 欄位,型別為 VARCHAR2(15),而 Student類有一個自定義型別屬性
alter table students add phone varchar2(15);
alter table students drop column phone;
java程式碼:
PhoneNumber 類定義型別的 phoneNumber 屬性。
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 String getAsString() {
return countryCode + "-" + stateCode + "-" + number;
}
// Setters and getters
}
public class Student{
private Integer id;
private String name;
private String email;
private PhoneNumber phone;
// Setters and getters
}
xml配置:
<insert id="insertStudent" parameter Type="Student">
insert into students(name,email,phone)
values(#{name},#{email},#{phone})
</insert>
這裡,引數物件中的屬性phone的值需要傳遞給#{phone};而引數物件的屬性phone是 PhoneNumber型別。但是,MyBatis 並不知道該怎樣來處理這個型別的物件。
為了讓MyBatis明白怎樣處理這個自定義的Java物件型別,如PhoneNumber,我們可以建立一個自定義的型別處理器,MyBatis提供了抽象類BaseTypeHandler<T> ,我們可以繼承此類建立自定義型別處理器。
程式碼如下所示:
package com.ijavac.typehandlers;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.ijavac.pojo.PhoneNumber;
public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>{
//遇到PhoneNumber引數的時候應該如何在ps中設定值
@Override
public void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, parameter.getAsString());
}
//查詢中遇到PhoneNumber型別的應該如何封裝(使用列名封裝)
@Override
public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException {
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));
}
}
注意:使用ps.setString()和rs.getString()方法是 :因為在資料庫的表中phone列是VARCHAR型別。
最後一旦我們實現了自定義的型別處理器,我們需要在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">
<configuration>
<properties resource="application.properties" />
<type Handlers>
<type Handler handler="com.ijavac.typehandlers.PhoneTypeHandler" />
</type Handlers>
</configuration>
註冊PhoneTypeHandler後, MyBatis就能夠將Phone型別的物件值儲存到VARCHAR型別的列上。
2.1.7 settings元素: 全域性引數設定
注意:大多數情況下,【這些引數使用它們的預設值即可】
為滿足應用特定的需求,MyBatis預設的全域性引數設定可以被覆蓋掉,如下所示:
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25000" />
<setting name="safeRowBoundsEnabled" value="false" />
<setting name="mapUnderscoreToCamelCase" value="false" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="OTHER" />
<setting name="lazyLoadTriggerMethods" value="equals,clone,hash Code ,to String" />
<setting name="proxyFactory" value="JAVASSIST" />
<setting name="aggressiveLazyLoading" value="true" />
<setting name="logImpl" value="LOG4J " />
<setting name="logPrefix" value="LOG4J " />
<setting name="callSettersOnNulls" value="false " />
</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="OTHER" />
<!-- 指定物件的哪個方法觸發一次延遲載入。 -->
<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>
2.1.8 mappers元素: SQL對映
SQLMapper檔案中包含的SQL對映語句將會被應用通過使用其標籤中的id值來執行。我們需要在mybatis-config.xml檔案中配置SQLMapper檔案的位置。
<mappers>
<mapper resource="com/ijavac/mappers/StudentMapper.xml" />
<mapper url="file:///D:/mybatisdemo/app/mappers/StudentMapper.xml" />
<mapper class="com.ijavac.mappers.StudentMapper" />
<package name="com.ijavac.mappers" />
</mappers>
以上每一個<mapper> 標籤都可以從不同型別的資源中載入對映mapper:
resource屬性用來指定在classpath中的mapper檔案。
url屬性用來通過完全檔案系統路徑或者web URL地址來指向mapper檔案
class屬性用來指向一個mapper介面
package屬性用來指向可以找到Mapper介面的包名
2.2 使用Java API配置MyBatis (屬於瞭解的內容,因為有了靈活的配置配置方法,這個方式幾乎不用)
MyBatis的SqlSessionFactory介面除了使用基於XML的配置建立外也可以通過JavaAPI程式設計式地被建立。每在XML中配置的元素,都可以程式設計式的建立。
因為mybatis框架讀取了我們配置的mybatis-config.xml中配置資訊之後,然後利用這些資訊去執行程式碼創建出我們需要的SqlSessionFactory,再從而進一步得到sqlSession,最後再進行各種資料庫操作。
所以其實我們完全可以不去配置任何資訊直接把資訊寫在程式碼中,然後在按著之前的順序創建出我們需要的SqlSessionFactory,再從而進一步得到sqlSession,最後再進行各種資料庫操作。只是這樣做再大多數時候都會降低程式碼的靈活性,所以我們基本上接觸的框架都是有相應的配置檔案的.
例如:使用Java API建立SqlSessionFactory物件,之前是讀取配置檔案之後再建立,現在是自己把資訊寫到程式碼中,然後再建立該物件
public static SqlSessionFactory getSqlSessionFactory() {
SqlSessionFactory sqlSessionFactory = null;
try {
DataSourcedata Source = DataSourceFactory.getDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.getTypeAliasRegistry().registerAlias("student",Student.class);
configuration.getTypeHandlerRegistry().register(PhoneNumber.class, PhoneTypeHandler.class);
configuration.addMapper(StudentMapper.class);
sqlSessionFactory = new SqlSessionFactoryBuilder().
build(configuration);
}
catch (Exception e) {
throw new RuntimeException(e);
}
return sqlSessionFactory;
}
類似的,每個在XML中配置的元素,都可以程式設計式的建立.
注:這裡就不一一介紹了,因為絕大多數情況下我們還是不會把配置資訊直接寫到程式碼中的
2.3 自定義MyBatis日誌
MyBatis使用其內部LoggerFactory作為真正的日誌類庫使用的門面。其內部的LaggerFactory會將日誌記錄任務委託給如下的所示某一個日誌實現,日誌記錄優先順序由上到下順序遞減:
jar 包 加 配置檔案
SLF4J
Apache Commons Logging
Log4j2
Log4j
JDK logging
如果MyBatis未發現上述日誌記錄實現,則MyBatis的日誌記錄功能無效,如果你的執行環境中,在classpath中有多個可用的日誌類庫,並且你希望MyBaits使用某個特定的日誌實現,你可以通過呼叫以下其中一個方法:
org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useLog4J2Logging();
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging();
org.apache.ibatis.logging.LogFactory.useStdOutLogging();
注:
如果你想自定義MyBatis日誌記錄,你應該在呼叫任何其它方法之前呼叫以上的其中一個方法
相關推薦
Mybatis入門以及配置檔案解析
一 mybatis入門 1.1 mybatis是什麼 MyBatis是一個簡化和實現了 Java 資料持久化層(persistence layer)的開源框架,它抽象了大量的JDBC冗餘程式碼,並提供了一個簡單易用的API和資料庫互動。
mybatis——config全域性配置檔案解析
原文:https://www.cnblogs.com/pjfmeng/p/7677773.html 在全集配置檔案中引入dtd約束“http://mybatis.org/dtd/mybatis-3-config.dtd”,主要有以下幾個標籤,現在詳細解釋下這幾個標籤的使用 1、prop
nginx1-dns域名解析|nginx入門|win下搭建|配置檔案解析
DNS域名解析器 DNS,域名系統,是網際網路上作為域名和IP地址相互對映的一個分散式資料庫 目的:將域名轉化成ip 過程 ------------------本機------------------ 1.輸入網址(www.163.com) 2.瀏覽器檢查快取中有沒有這個域名
JavaEE-SSM:007 Mybatis的配置檔案解析(4)
1.系統級別的typeHandler 2.自定義typeHandler 想要自己實現typeHandler,需要實現TypeHandler<T>介面,T就是你要轉換的Java型別 setParameter(PreparedSta
JavaEE-SSM:006 Mybatis的配置檔案解析(3)
別名主要用於Mapper的xml檔案指定輸入型別或者返回結果型別的名稱的時候,替代全限定名。(前文已經提及如何使用別名) 1.系統級別的typeAlias(類型別名) 2.自定義別名 這裡的alias屬性值得是
JavaEE-SSM:005 Mybatis的配置檔案解析(2)
setting配置不常用,給出配置說明: 本文給出Setting配置的全量程式碼: <settings> <setting name="cacheEnabled" value="true"
JavaEE-SSM:004 Mybatis的配置檔案解析(1)
1.配置項:不可顛倒順序 2.Properties配置 好處就是:一處配置,多處使用。當然不嫌麻煩,直接配置,不使用property也是可以的。 在Properties下配置相關的配置Property:name是引用的時候的名稱
JavaEE-SSM:009 Mybatis的配置檔案解析(6)
檔案型別轉換器(不常用) 假設資料庫有blob格式的欄位儲存需求: 對應著POJO的byte陣列: ResultMap中有對應的typeHandler配置: 當然,我們可以在POJO中使用InputStream替代byte陣列,但
JavaEE-SSM:008 Mybatis的配置檔案解析(5)
1.系統級列舉typeHandler--EnumOridinalTypeHAndler 資料庫儲存為數字 //建立一個列舉 public enum SexEnum { MALE(1,"男"), FEMALE(0,"女"); private int id;
ehcache配置檔案解析以及記憶體結構
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation=
Mybatis配置檔案解析過程詳解
記錄是一種精神,是加深理解最好的方式之一。 這篇文章能夠幫你 學會如何對Mybatis進行有效配置,理解對應的配置含義,知其然知其所以然。 學會在Mybatis預設實現無法滿足需求的時候怎麼去擴充套件。 從構建SqlSessionFactory說起
mybatis-Config.xml全域性配置檔案解析
一:mybatis-Config.xml配置檔案的內容和配置順序如下 properties(屬性)settings(全域性配置引數)typeAiases(類型別名)typeHandlers(型別處理器)objectFactory(物件工廠)plugins(外掛)enviro
mybatis框架搭建環境以及配置檔案
專案檔案位置(暫時這樣放實際開發不是這樣的) Configuration.xml 檔案mybatis配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//
Spring+SpringMVC+MyBatis深入學習及搭建(三)——MyBatis全域性配置檔案解析
MyBatis的全域性配置檔案SqlMapConfig.xml,配置內容和順序如下: properties(屬性) setting(全域性配置引數) typeAliases(類名別名) typeHandlers(類名處理器) objectFactory(物件工廠) plugins(外掛) environm
MyBatis簡單例項及配置檔案解析
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/
mybatis generator 配置檔案解析
這是mybatis3 generator 配置檔案,包括了主要的配置引數,具體的配置說明請在文章結尾處下載 完整的配置應用。 應用是基於myeclipse的java應用。 文章中的MBG指的就是MybatisGenerator這個工具。 <?xml version="1.0" encoding=
MyBatis主配置檔案解析
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/
mybatis配置檔案解析
技術實現夢想--在mybatis中的mybaits-config.xml中的配置項檢視配置檔案中的連線 :http://mybatis.org/dtd/mybatis-3-config.dtd 便可清楚mybatis中屬性的書寫順序<!ELEMENTconfigurat
MyBatis 全域性配置檔案解析
### 1. dtd約束 1.config <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.or
mybatis原始碼配置檔案解析之一:解析properties標籤
mybatis作為日常開發的常用ORM框架,在開發中起著很重要的作用,瞭解其原始碼對日常的開發有很大的幫助。原始碼版本為:3-3.4.x,可執行到github進行下載。 從這篇文章開始逐一分析mybatis的核心配置檔案(mybatis-config.xml),今天先來看properties標籤的解析過程。