深入理解MyBatis核心技術01 --- MyBatis的2種基本使用方式詳解(基於註解和xml)

        在我們的日常開發中MyBatis是使用的比較多的orm框架之一,以前本患者僅僅停留在會用的層面上,但是對於一些原理性的東西基本都是知其然不知其所以然。所以最近這段時間打算和大家一起討論一下MyBatis的一些核心原理。

       首先今天先和大家分享一下本人使用MyBatis框架的兩種方法,一種是基於註解的方式,另外一種是編寫xml映射文件,首次我們來到官網:https://mybatis.org/mybatis-3/     進入之後是如下圖所示的界面:

        從上圖中可以看到MyBatis的基本介紹,但是最重要的一點是下方的五星紅旗,激動吧,MyBatis官方網站上支持中文版本的,因此我們點擊五星紅旗,切換到中文版本,如下圖所示:

      我們首先點擊上圖中的項目的GIT代碼庫 進入到MyBatis 的下載頁面,如下圖所示:

       首先我們點擊下載最新的版本,進入到如下圖所示的界面:

        點擊下方的zip包的超鏈接,下載MyBatis框架的包, 其中mybatis-3.5.3這個是可運行的文件,下面的兩個是源碼文件包。下載完成之後我們解壓mybatis-3.5.3這個包,解壓後的目錄如下所示:

        其中我們pdf就是MyBatis的使用手冊,mybatis-3.5.3.jar就是我們需要導入到程序中的jar包,lib目錄下存放的是我們可能要用到的一些jar包,並不是Mybatis依賴的jar包.      

       好了,關於mybatis 的下載就先到這裏了,我們先來寫一個入門級的demo。

       首先打開我們的開發工具,創建一個新的Java工程,並創建相應的包結構。如下圖所示(開發工具暫時用的sts):

 

        其中我們在lib目錄下導入數據庫驅動包和Mybatis包,同時我們還需要一個日誌的工具,這裏我們使用log4g,日誌包可以在Mybatis框架的lib目錄中找到。conf目錄是存放配置文件的目錄。創建好了之後我們在pojo中新建一個實體類,Fruit,該類中易功有四個屬性,分別是id,name,area,color,同時我們爲這四個屬性創建set/get方法,以及toString方法。具體代碼如下圖所示:

private Integer id;
	private String fruitName;
	private String area;
	private String fruitColor;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getFruitName() {
		return fruitName;
	}
	public void setFruitName(String fruitName) {
		this.fruitName = fruitName;
	}
	public String getArea() {
		return area;
	}
	public void setArea(String area) {
		this.area = area;
	}
	public String getFruitColor() {
		return fruitColor;
	}
	public void setFruitColor(String fruitColor) {
		this.fruitColor = fruitColor;
	}
	@Override
	public String toString() {
		return "Fruit [id=" + id + ", fruitName=" + fruitName + ", area=" + area + ", fruitColor=" + fruitColor + "]";
	}

     接着我們需要準備數據了,打開mysql ,新建一個數據庫mybatis,然後再新建一張fruit表,表結構如下所示:

 

     好了,數據庫環境準備完成之後我們就回到開發工具中,準備我們的第一個demo了。

     emmmm.........有點不知道怎麼下手,還是先打開我們下載的zip包中的pdf文檔吧,我們打開文檔之後選擇 Getting Started

    然後可以看到如下內容  : 

         這裏說的意思就是從xml來構建SqlSessionFactory這個對象,並且給了一段示例的代碼 ,這段代碼的意思就是獲取SqlSessionFactory這個對象,首先我們把這段代碼複製到我們的工程中,我們知道這段代碼肯定是會產生一個SqlSessionFactory對象的,因此我們新建一個util包,在該包中新建一個工具類,將上述示例代碼封裝成一個方法,代碼如下:

public class CommonsUtils {
	
	public static SqlSessionFactory getSqlSessionFactory() throws IOException {
		
		String resource = "org/mybatis/example/mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory =
		new SqlSessionFactoryBuilder().build(inputStream);
		return sqlSessionFactory;
	}

}

      可以看到,上述代碼實在加載一個xml文件,而SqlSessionFactory對象是根據這個配置文件來創建 的,所以我們也需要一個mybatis-config.xml的配置文件,好了,回到官方文檔上,我們可以看到這樣一句話:

        我們可以看到 上面說從 XML 文件中構建 SqlSessionFactory 的實例非常簡單,我們可以用任意的InputStream實例來加載該文件 同時可以用字符串形式的xml或者在文件系統中使用任意的 URL 形式指定路徑的文本文件都可以。但是他們建議我們在類路徑下創建該文件,大概的意思看懂了就可以,這裏就不逐字逐句的給大家翻譯了 (英語能力實在有限,詳細的中文意思推薦去官網上看)。 所以我們同從官方的建議,在類路徑conf下創建一個mybatis-config.xml文件,這裏解釋一下conf默認和類路徑一致。

       那麼創建好了之後我們需要在該配置文件中寫一些什麼東西呢? 好了 ,我們回到文檔上,會發現文檔上提供了一個樣例。如下圖所示:

我們將上述的示例複製到我們創建的xml中去。如下圖所示:

        按照我們以往的開發經驗來猜測,dataSource標籤中的內容應該是和數據源相關的,因此這裏我們將自己數據庫的信息寫上去即可。那麼還有一個mapper標籤的中的內容應該寫什麼呢? 我們看到官方給出的也是一個xml文件,好了,我們繼續看文檔,發現文檔中還有一種方式構建SqlSessionFactory,不使用xml配置文件:

         這裏先放一放,稍後再給大家演示這種方式。我麼繼續往下看文檔,發現後面是告訴我們怎麼從SqlSessionFactory中獲取 SqlSession對象,同樣的給我們提供了一段簡單的代碼示例,如下所示:

我們繼續將上述示例代碼拷貝到我們的工具類中,封裝成一個方法,如下圖所示:

        到這裏我們應該有一種直覺,Blog肯定是一個pojo對象,理論上應該對應一張數據表,好了,我們繼續往下看文檔,發現下面還有一段示例代碼,如下圖所示:

        可以看到官方更推薦下面這種方式的用法,使用一個接口來完成查詢的操作,該接口定義了查詢語句的參數和查詢的結果類型。好了,我們繼續將上述代碼拷貝到工具類中單獨封裝成方法,稍後我們逐一來演示這兩種方式。接着我們嘗試將Blog修改成本次我們自己寫的實體類Fruit,修改完成之後我們的工具類CommomUtils完整的代碼如下:

public class CommonsUtils {
	
	public static SqlSessionFactory getSqlSessionFactory() throws IOException {
		
		String resource = "org/mybatis/example/mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory =
		new SqlSessionFactoryBuilder().build(inputStream);
		return sqlSessionFactory;
	}
	
	public static SqlSession getSqlSession(SqlSessionFactory sqlSessionFactory) {
		try (SqlSession session = sqlSessionFactory.openSession()) {
			Fruit blog = session.selectOne(
			"org.mybatis.example.BlogMapper.selectBlog", 101);
			}
		return null;
	}
	public static SqlSession getSqlSession2(SqlSessionFactory sqlSessionFactory){
		try (SqlSession session = sqlSessionFactory.openSession()) {
			FruitMapper mapper = session.getMapper(FruitMapper.class);
			Fruit fruit = mapper.selectFruit(101);
			}
		return null;
	}

}

    好了,爲我們繼續往下看文檔,發現了下面還有一段基於xml映射語句的示例,我們發現了該xml中有一條sql語句,如下所示:

   我們再接着往下看,下面有兩段話用來解釋上述xml文件:

       官方說我們在一個sql映射文件中可以聲明多個sql語句,我們上面的示例代碼的意思就是通過一個namespace(名稱空間)指定一個xml映射文件,映射文件中定義了一條id是selectBlog的sql語句,該sql語句的傳入參數是id。我們調用的方式有兩種:                    第一種就是通過SqlSession 對象的selectOne方法,該方法有兩個參數,第一個參數是 namespace+sql語句的id組成字符串的形式,第二個參數是sql語句的執行條件參數。                                                                                                                                    第二種方式就是通過一個接口來指定查詢的sql語句,接口的所在的包對應namespace,接口中的方法名對應sql映射文件中的sql語句的id ,方法的參數就是sql語句的執行條件。好了,我們仔細看一下文檔中這個地方,這裏描述的兩種方式不就是上述提供的示例代碼嘛。因此我們將這段示例的映射文件拷貝,再類路徑下新建xml文件,並且將內容稍作修改如下圖所示:

       這裏需要注意的是我們的namespance要和包名以及映射文件的路徑保持一致。並且我們將示例文件中的內容改成我們自己定義的內容。好了,接着我們再回到mybatis-config.xml文件中,再mapper標籤中指定一下FruitMapper.xml的路徑,代碼如下圖所示:

              

        這裏需要注意的是如果是使用的resourcel屬性的話我們需要寫相對路徑,即從類路徑開始寫。到這裏基本的準備工作已經差不多了,我們將CommonsUtils類在稍作一些修該,修改之後的代碼如下所示:

public class CommonsUtils {
	
	public static SqlSessionFactory getSqlSessionFactory() throws IOException {
		
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory =
		new SqlSessionFactoryBuilder().build(inputStream);
		return sqlSessionFactory;
	}
	
	public static Fruit getFruit(SqlSessionFactory sqlSessionFactory) {
		Fruit fruit = null;
		try (SqlSession session = sqlSessionFactory.openSession()) {
				fruit = session.selectOne(
			"com.wcan.poet.mybatis.mapper.FruitMapper.selectFruit", 1);
			}
		return fruit;
	}
	public static Fruit getFruit2(SqlSessionFactory sqlSessionFactory){
		Fruit fruit = null;
		try (SqlSession session = sqlSessionFactory.openSession()) {
			FruitMapper mapper = session.getMapper(FruitMapper.class);
			fruit = mapper.selectFruit(1);
			}
		return fruit;
	}
}

修改完成之後我們在測試包test下新建一個測試類MybatisTest,並且在該類中調用utils中的getFruit方法,代碼如下:

public class MyBatisTest {
	
	@Test
	public void test01() throws IOException {
		SqlSessionFactory sessionFactory = CommonsUtils.getSqlSessionFactory();
		Fruit fruit = CommonsUtils.getFruit(sessionFactory);
		System.out.println(fruit);
	}
}

       在該方法中,我們先獲取一個SqlSessionFactory對象,再將該對象傳入到getfruit方法中,最後返回一個Fruit對象。我們執行該方法,發現報出來一個異常,該異常信息如下所示:

org.apache.ibatis.exceptions.PersistenceException: 
	### Error building SqlSession.
	### The error may exist in com/wcan/poet/mybatis/mapper/FruitMapper.xml
	### Cause: org.apache.ibatis.builder.BuilderException: 
	Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException:
 	Error parsing Mapper XML. The XML location is 'com/wcan/poet/mybatis/mapper/FruitMapper.xml'.
  	Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. 
  	Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Fruit'.  
  	Cause: java.lang.ClassNotFoundException: Cannot find class: Fruit
	... 35 more

       上述的異常信息就是說我們在 com/wcan/poet/mybatis/mapper/FruitMapper.xml文件中定義的Fruit類找不到,這裏我們在回到Fruit類中,發現resultType屬性我們寫了一個Fruit ,但是沒有加包名,因此Mybatis在運行的時候找不到這個類,於是我們先來加上包名,將resultType屬性的值改成: com.wcan.poet.mybatis.pojo.Fruit  即可,接着我們繼續執行,可以發現在控制檯打印出了sql語句,但是查詢結果是空的。如下圖所示:

好了,到這裏說明我們的代碼應該沒有問題了,我們在數據庫中先放一條數據,

        接着再次執行一遍test01方法,發現還是返回的null對象,我們再來看一下映射文件中的SQL語句,查詢條件是* 也就是說默認查詢所有的字段,但是有一個問題,我們在程序中的變量名是駝峯命名方式,而數據庫中則是採用下劃線連接。兩個並不是對應的,所以即使查詢到了數據也無法封裝到對象中,熟悉sql 的同學此時肯定想到了別名,是的,別名可以解決這個問題,我們修改sql語句,爲每個字段加上別名,如下所示:

select id,fruit_name fruitName,area,fruit_color fruitColor  from fruit where id = #{id}

再次運行即可查詢到一條結果了:

  好了,接下來我們繼續調用第二種方法來查詢數據,編寫test02方法,代碼如下:

	
	@Test
	public void test02() throws IOException {
		SqlSessionFactory sessionFactory = CommonsUtils.getSqlSessionFactory();
		Fruit fruit = CommonsUtils.getFruit2(sessionFactory);
		System.out.println(fruit);
	}

      發現同樣的可以查詢到數據。好了,入門程序就先介紹到這裏了。明天可繼續給大家講解通過註解的方式來使用Mybatis框架,小編要去睡覺了。晚安 

 

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