MyBatis學習一

1.   MyBatis介紹

  • 1.  MyBatis完成CRUD(掌握)
  • 2.  MyBatis的核心對象(掌握)
  • 3. MyBatis使用細節(掌握)
  1. ORM概述

2.1.  流行的ORM框架java

1.JPA:自己是一種ORM規範,不是ORM框架.由各大ORM框架提供實現.mysql

2.Hibernate:目前最流行的ORM框架.設計靈巧,性能通常(本身去控制性能,不是很好控制),文檔豐富.(徹底自動操做)面試

Hibernate是一個完整的ORM框架,常規CRUD咱們不須要寫一句SQL;sql

3.MyBatis:本是apache的一個開源項目iBatis,提供的持久層框架包括SQL Maps和Dao,容許開發人員直接編寫SQL(更好靈活).(Sql操做方式)數據庫

MyBatis 並非一個完整的ORM框架,由於咱們還須要本身去寫所有SQLapache

2.2.  JDBC操做數據庫缺陷安全

首先,經過jdbc也能實現對象實體和數據庫關係的映射.那就是採用硬編碼方式,爲每一種可能的數據庫訪問操做提供單獨的方法。 也就是各類Dao(UserDao DeptDao等)。網絡

最大的缺點就是:session

   一、sql寫在JAVA代碼中改修改sql必須修改代碼,須要從新編譯。mybatis

   二、有不少重複性的操做(好比獲取鏈接,釋放資源等)

2.3.  ORM框架的操做數據庫關係方式有不少種,經常使用的有兩種    

2.3.1.   Sql操做方式(對jdbc進行封裝)(mybatis的實現方式)

        把SQL配置到配置文件中,經過不一樣SQL中完成對象實體和數據庫關係相互轉換的操做。

2.3.2.   完整操做(JPA、Hibenate實現方式)

       直接映射的是對象實體和數據庫關係映射。操做數據庫關係,不用寫SQL由框架本身生成。

 

2.4.  ORM框架工做原理

一、以必定的映射方式,把實體模型和數據庫關係的映射

二、ORM框架啓動時加載這些映射和數據庫配置文件

三、ORM經過對最原生jdbc的封裝提供更加便利的操做API

四、Dao經過ORM提供的便捷API以對象的方式操做數據庫關係。

 

  1. MyBatis的認識

3.1.  MyBatis的起源

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,而且更名爲MyBatis 。

2013年11月遷移到Github。

iBATIS一詞來源於「internet」和「abatis」的組合,是一個基於Java的持久層框架。

iBATIS提供的持久層框架包括SQL Maps(XML映射配置)和Data Access Objects(Dao)

3.2.  MyBatis的介紹

MyBatis 是一個支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架。

MyBatis 消除了幾乎全部的JDBC代碼和手工設置參數以及結果集的檢索。

MyBatis 使用簡單的 XML或註解用於配置和原始映射,將接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。

MyBatis不能自動建立表,若是可以自動建表,必須本身先準備好建表的sql語句。

  1. MyBatis完成CRUD

4.1.  操做前的準備工做

建立一個java項目?略過

4.1.1.   導入相應的9個jar包

MyBatis是一個框架,我們說了。在Java中框架就是一組Java類最後打成jar包。所以,不僅是這個框架,之後我們學習的全部框架。在使用前都要先導入相應 的jar包。

在導入jar包以前,咱們得先說一下,MyBatis是操做數據庫的框架。我們之前學JDBC的時候說過:要操做數據庫,必定不要忘了導入相應的數據庫驅動包。

  注:驅動包就是各大數據庫廠商根據JDBC規範實現的jar包(忘了的同窗能夠去看JDBC第一天的筆記)

 

而後找到MyBatis(相關文件咱們已經準備好,你們也能夠到網上進行自行下載),再導入MyBatis的核心包與依賴包。

下圖爲咱們使用MyBatis要導入的包:

 

 

4.1.2.   準備相應的表

我們對數據庫進行操做,確定須要準備表。這沒啥好說的。

如今直接引入咱們準備好的product表便可:

 

 

 

4.1.3.   準備相應的domain

建立一個Product對象,和數據庫的表對應

注:類的名稱和類型都和咱們的product表相對應匹配

public class Product {

         private       Long id;

         //商品名稱

         private String productName;

         //品牌

         private String brand;

         //供應商

         private String supplier;

         //零售價

         private Double salePrice;

         //進價

         private Double costPrice;

         //折扣比例

         private Double cutoff;

         //商品分類編號

         private Long dir_id;

          

   //提供getter與setter...

}

4.2.  小結

準備步驟:

1 導包

2 建表(product)

3 domain(Product)

4 準備dao層(CRUD)

5 測試(不是必需的)

注意:咱們要引哪些包?

1 必定要引入驅動包(不要忘了)

2 導入mybatis的核心包

3 導入mybatis的依賴包

4.3.  product的Dao層準備

/**

 * 商品的持久操做

 */

public interface IProductDao {

         /**

          * 添加一個商品

          */

         void save(Product p);

        

         /**

          * 更新一個商品

          */

         void update(Product p);

        

         /**

          * 刪除一個商品

          */

         void delete(Long id);

        

         /**

          * 獲得一個商品

          */

         Product get(Long id);

         /**

          * 獲得全部商品

          */

         List<Product> getAll();

}

  1. MyBatis核心配置文件

5.1.  看文檔

一切準備就緒。接下來就是開始使用MyBatis了。可是問題來了,怎麼用呢?

該文檔雖然只有50多頁,可是已經足夠我們學習了。

先來入個門吧:入門開始,除了介紹什麼是MyBatis以後,就在說一個核心對象:SqlSessionFactory,接下來,我們就是要千方百計拿到這個核心對象。

    那SqlSessionFactory對象怎麼拿到:直接找到文檔中的從 XML 中構建 SqlSessionFactory這一小節開始便可。

5.2.  從這一節中咱們能夠看出如下幾個點:

    1 咱們須要準備一個核心的xml文件

    2 拿到SqlSessionFactory以前須要讀取核心的xml配置文件

    3 須要構造者(SqlSessionFactoryBuilder)來建立它

5.3.  MyBatis-Config.xml

    好了,大概介紹完畢後,咱們能夠開始準備核心配置的xml文件了

    在資源文件夾下面建立一個文件,取名爲MyBatis-Config.xml

    以把文檔中的配置拷備過來(先作了解測試,等功能能夠用起來後,再本身去寫這個配置)

5.4.  配置MyBatis-Config.xml提示信息

 

5.5.  核心配置的一個簡單介紹:

咱們須要準備幾個東西須要一個環境environments

environments 裏面兩個內容(transactionManager ,dataSource )

dataSource : driver,url,username,password(鏈接數據庫的最小單位)

<configuration>

         <!-- 環境們 (不少環境的意思)

                  default:默認使用哪個環境(必需對應一個環境的id)

          -->

         <environments default="development">

                  <!--

                           一個環境  id:爲這個環境取惟一一個id名稱

                  -->

                  <environment id="development">

                           <!-- 

                                    事務管理   type:JDBC(支持事務)/MANAGED(什麼都不作)

                           -->

                           <transactionManager type="JDBC" />

                           <!-- 數據源, 鏈接池  type(POOLED):MyBatis自帶的鏈接池 -->

                           <dataSource type="POOLED">

                                    <!-- 鏈接數據庫的參數 -->

                                    <property name="driver" value="com.mysql.jdbc.Driver" />

                                    <property name="url" value="jdbc:mysql:///mydb" />

                                    <property name="username" value="root" />

                                    <property name="password" value="admin" />

                           </dataSource>

                  </environment>

         </environments>

   <!-- 這個mappers表明的是相應的ORM映射文件 -->

         <mappers>

                  <mapper resource="cn/itsource/domain/ProductMapper.xml" />

         </mappers>

 

</configuration>

5.6.  抽取數據庫信息配置文件

如今我們的關於數據庫鏈接信息已經在配置文件(XML)中,可是更多時候,咱們仍是會把配置文件的信息放到db.properties中。(因爲properties的結構簡單,便於修改,而這個文件只放數據庫的鏈接信息也更好的體現了職責分離)。

其實,在官方文檔的核心文件配置,直接就是使用的推薦properties的方式

只須要咱們作以下修改便可:

5.6.1.   MyBatis-Config.xml

<configuration>

         <!-- 引入Properties文件 -->

         <properties resource="db.properties"></properties>

         <environments default="development">

                  <environment id="development">

                           <transactionManager type="JDBC" />

                           <dataSource type="POOLED">

                                    <!-- 根據key拿到properties中的value值 -->

                                    <property name="driver" value="${db.driver}" />

                                    <property name="url" value="${db.url}" />

                                    <property name="username" value="${db.username}" />

                                    <property name="password" value="${db.password}" />

                           </dataSource>

                  </environment>

         </environments>

         <mappers>

                  <mapper resource="cn/itsource/domain/ProductMapper.xml"/>

         </mappers>

</configuration>

5.6.2.   db.properties

db.driver=com.mysql.jdbc.Driver

db.url=jdbc:mysql:///test0303

db.username=root

db.password=admin

5.7.  映射文件

核心文檔已經搭建準備就緒,內心還有一點小激動。

可是老是以爲,少了點什麼? 是什麼呢?

請你們回顧與分析咱們剛纔學習的內容:

MyBatis是一個ORM映射框架,請問ORM體如今哪?

核心文件中有一個mappers,它指向了一個映射文件。映射文件在哪?

不是說好的MyBatis要寫SQL語句麼?SQL語句又在哪裏?

一切的一切都會出如今咱們的下一個章節:對象與關係的映射!敬請關注。

 

如今直接寫xml是沒有提示了,在xml的約束中,我們講過,當有約束的時候,xml就會有提示。

       提示:出門再拐 在xml那一章的schema與dtd約束

而如今我們的約束是在網絡上。在Eclipse中,咱們能夠找到相應的約束文件,而後配置到本身本地便可。

5.8.  對象與關係的映射(ORM)

接下來,解決上一章的幾個問題。

直接找到咱們文檔中的探究已映射的SQL語句,在這裏,我就能夠看到一段xml(以下圖),這個xml就是我們須要的映射文件,它就能夠體現出ORM,而且在這裏面,也能夠愉快的寫sql語句了。

 

 

    在這裏,咱們能夠看懂一些配置的意思,可是也有一些東西不是很明白。在下面的實例中,我已經對每一句配置準備好了相應的解釋:

<?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的主要功能就是寫sql

         mapper:根

         namespace:命令空間 (用來肯定惟一) 之前這個是能夠不加的,如今必需加

     namespace的值,規則的:映射文件XxxMapper.xml所在的包+domain類名+Mapper

 -->

<mapper namespace="cn.itsource.mybatis.day1._1_hello.ProductMapper">

         <!--

                  select : 這裏面寫查詢語句

                  id:用來肯定這條sql語句的惟一

                              之後咱們肯定惟一,也就是找sql語句 : namespace +.+ id

                            例: cn.itsource.mybatis.day1._1_hello.ProductMapper.get

                  parameterType : 傳入的參數類型  long:大Long  _long:小long (具體的對應請參見文檔)

                  resultType : 結果類型(第一條數據返回的對象類型) 本身的對象必定是全限定類名

          -->

         <select id="get" parameterType="long" resultType="cn.itsource.domain.Product">

                  select * from product where id = #{id}

         </select>

</mapper>

5.9.  在上述文件中,但願你們注意幾個規範:

① 咱們的映射文件通常狀況下是和它對應的domain實體類在同一個層級

② 這個映射文件的名稱通常叫作 XxxMapper.xml (Xxx表明的是實體類名稱)

③ namespace的名稱爲了肯定惟一性,請你們根據個人要求取名

    如咱們有一個類:

    cn.itsource.domain.Product / cn.itsource.domain.Student

    那這裏取名應該是:

    cn.itsource.domain.ProductMapper /cn.itsource.domain.StudentMapper

④ 除了MyBatis支持的類型,其它的類型都統統使用全限定名   

  1. 完成數據的CRUD

核心文件有了,映射文件也有了。如今能夠來完成我們的CRUD了吧!

可是應該從哪裏開始好呢?

還記得我們前面說過須要的核心對象SqlSessionFactory吧

我們說過,須要經過它去拿到一個SqlSession對象(至關於JDBC的鏈接)

必須要有SqlSession這個對象,咱們才能夠去執行相應的Sql

6.1.  拿到SqlSession對象

官方文檔從XML 中構建 SqlSessionFactory這一章中,除了配置的核心xml,在上面咱們還能夠看到幾句代碼(以下圖),如今我們就來詳細分析一下這幾句代碼是什麼意思:

 

 

 咱們簡單解釋一下上面的代碼:讀取核心文件,而後再經過SqlSessionFactoryBuilder構建者來建立一個SqlSessionFactory工廠。

注:上面的sqlMapper實際上是一個SqlSessionFactory工廠對象(它取名不是很直觀)

 

官方文檔從SqlSessionFactory 中獲取 SqlSession這一章中,咱們能夠看到代碼(下圖),而後再拿到SqlSession,而且在這裏面,還附上了我們怎麼調用sql的代碼。

6.2.  工具類的抽取MyBatisUtils

對於MyBatis的工具類抽取,我們直接使用靜態工具的單例模式。

注:幾種單例模式的區別與使用(單例工具與靜態工具的區別),你們能夠去看基礎增強那天的課程。

 

import java.io.Reader;

 

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 MyBatisUtils {

         // 保證SqlSessionFactory是單例

         private static SqlSessionFactory sqlSessionFactory;

 

         // SqlSessionFactory相似於JPA的EntityManagerFactory,Hibernate的SessionFactory

         // SqlSession 相似於JPA的EntityManager,Hibernate的Session

 

         static {

                  try {

                           Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");

                           sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

                  } catch (Exception e) {

                           e.printStackTrace();

                           throw new RuntimeException("解析MyBatis的配置文件或者映射文件出現異常:" + e.getMessage());

                  }

         }

 

         // 對外提供一個類

         public static SqlSession getSession() {

                  return sqlSessionFactory.openSession();

         }

}

 

6.3.  查詢一條數據

根據上面咱們get到的技能,使用MyBatis查詢一條數據!

 

 

你們要注意我們傳過去的參數,還有在SQL接收的參數!【課堂分析】

傳過去的變量名稱和#裏面的字符串名稱不是一回事!

 

講到這裏,我們再對整個MyBatis的流程再進行一次分析。

①:咱們須要核心文件(提供聯繫數據庫的環境)

②:須要映射文件(提供ORM與運行的SQL語句)

③:拿到SqlSession對象,用於執行SQL

@Override

public Product get(Long id) {

         SqlSession sqlSession = null;

         try {

                  sqlSession = MyBatisUtils.getSession();

                  return sqlSession.selectOne(NAME_SPACE + "get", id);

         } catch (Exception e) {

                  e.printStackTrace();

                  throw new RuntimeException("ProductDaoImpl.get出現異常:" + e.getMessage());

         } finally {

                  if (sqlSession != null) {

                           sqlSession.close();

                  }

         }

}

6.4.  junit來一個測試(必須的)

寫代碼要測試,這是一個好習慣!

public class ProductDaoTest {

 

         IProductDao productDao = new ProductDaoImpl();

 

         @Test

         public void testGet() {

                  Product product = productDao.get(1L);

                  System.out.println(product);

         }

 

}

6.5.  查詢全部數據

6.5.1.   代碼

@Override

public List<Product> getAll() {

         SqlSession sqlSession = null;

         try {

                  sqlSession = MyBatisUtils.getSession();

                  return sqlSession.selectList(NAME_SPACE + "getAll");

         } catch (Exception e) {

                  e.printStackTrace();

                  throw new RuntimeException("ProductDaoImpl.get出現異常:" + e.getMessage());

         } finally {

                  if (sqlSession != null) {

                           sqlSession.close();

                  }

         }

}

6.5.2.   映射文件

<!-- 返回相似仍然是Product:domain類 -->

<select id="getAll" resultType="cn.itsource.mybatis.day1._1_hello.Product">

         select * from product

</select>

6.5.3.   測試

@Test

public void testGetAll() {

         List<Product> list = productDao.getAll();

         for (Product product : list) {

                  System.out.println(product);

         }

}

6.6.  添加一條數據

注:添加的時候必定要記住提交事務(配置事務、表結構支持事務)

JDBC的事務是自動提交的,而JPA、Hibernate、MyBatis事務都是須要手動提交的

6.6.1.   代碼

@Override

public void save(Product product) {

         SqlSession sqlSession = null;

         try {

                  sqlSession = MyBatisUtils.getSession();

                  sqlSession.insert(NAME_SPACE + "save", product);

                  // JDBC的事務是自動提交的,而JPA、Hibernate、MyBatis事務都是須要手動提交的

                  sqlSession.commit();

         } catch (Exception e) {

                  e.printStackTrace();

                  throw new RuntimeException("ProductDaoImpl.get出現異常:" + e.getMessage());

         } finally {

                  if (sqlSession != null) {

                           sqlSession.close();

                  }

         }

}

6.6.2.   映射文件

<!-- void save(Product product); -->

<insert id="save" parameterType="cn.itsource.mybatis.day1._1_hello.Product">

         <!-- #{productName}==product.getProductName() -->

         insert into product(productName,salePrice,costPrice,cutoff,supplier,brand,dir_id)

         values

         (#{productName},#{salePrice},#{costPrice},#{cutoff},#{supplier},#{brand},#{dir_id})

</insert>

6.6.3.   測試

@Test

public void testSave() {

         Product product = new Product();

         product.setBrand("大力牌");

         product.setCostPrice(30.0);

         product.setCutoff(0.8);

         product.setDir_id(1L);

         product.setProductName("000000");

         product.setSalePrice(60D);

         product.setSupplier("東莞供應商");

         productDao.save(product);

}

添加數據的有時候我們須要拿到當前數據的主鍵。我們先移步到MyBatis細節一章的拿到返回主鍵部分!

 

6.7.  修改一條數據

6.7.1.   代碼

@Override

public void update(Product product) {

         SqlSession sqlSession = null;

         try {

                  sqlSession = MyBatisUtils.getSession();

                  sqlSession.update(NAME_SPACE + "update", product);

                  // JDBC的事務是自動提交的,而JPA、Hibernate、MyBatis事務都是須要手動提交的

                  sqlSession.commit();

         } catch (Exception e) {

                  e.printStackTrace();

                  throw new RuntimeException("ProductDaoImpl.get出現異常:" + e.getMessage());

         } finally {

                  if (sqlSession != null) {

                           sqlSession.close();

                  }

         }

}

6.7.2.   映射文件

<!-- void update(Product product); -->

<update id="update" parameterType="cn.itsource.mybatis.day1._1_hello.Product">

         <!-- #{productName}==product.getProductName() -->

         update product set productName=#{productName},salePrice=#{salePrice},costPrice=#{costPrice},

         cutoff=#{cutoff},supplier=#{supplier},brand=#{brand},dir_id=#{dir_id}

         where id=#{id}

</update>

6.7.3.   測試

@Test

public void testUpdate() {

         Product product = productDao.get(1L);

         System.out.println(product);

        

         product.setBrand("大力牌");

         product.setCostPrice(30.0);

         product.setCutoff(0.8);

         product.setDir_id(1L);

         product.setProductName("000000");

         product.setSalePrice(60D);

         product.setSupplier("東莞供應商");

         productDao.update(product);

        

         product = productDao.get(1L);

         System.out.println(product);

}

 

 

6.8.  刪除一條數據

6.8.1.   代碼

@Override

public void delete(Long id) {

         SqlSession sqlSession = null;

         try {

                  sqlSession = MyBatisUtils.getSession();

                  sqlSession.delete(NAME_SPACE + "delete", id);

                  // JDBC的事務是自動提交的,而JPA、Hibernate、MyBatis事務都是須要手動提交的

                  sqlSession.commit();

         } catch (Exception e) {

                  e.printStackTrace();

                  throw new RuntimeException("ProductDaoImpl.delete出現異常:" + e.getMessage());

         } finally {

                  if (sqlSession != null) {

                           sqlSession.close();

                  }

         }

}

6.8.2.   映射文件

<!-- void delete(Long id); -->

<delete id="delete" parameterType="id">

         delete from product where id=#{id}

</delete>

6.8.3.   測試

@Test

public void testDelete() {

         productDao.delete(1L);

         Product product = productDao.get(1L);

         System.out.println(product);

}

6.9.  CRUD注意事項

下面的點都很重要,是你們在使用MyBatis的時候常常出現的點。但願你們引發重視。出現問題的時候過來好好的來找。基本我們使用MyBatis中出的錯都在這裏。

使用框架的時候配置信息變多,在配置裏寫的都是字符串,並且常常是要對應的。由於,這裏但願你們要切記:寫的時候細心,出現錯誤找字符串要耐心,

1 主配置中未配置相應的mapper(固然,這個路徑也可能寫錯)

2 在代碼中調用Sql的時候路徑寫錯

3  Sql寫錯,這個應該還好找

4 當咱們在配置文件中不少地方若是寫錯,即使是你尚未使用也可能會報錯

5 寫Sql的標籤不須要所有一致(如添加不必定必需使用insert),可是它的屬性會不一樣

6 在傳入與返回參數時全限定類名寫錯

 

    在開發的時候,要邊作邊測試。 在某一步出現錯誤後,刪除新加的代碼看有沒有問題,若是刪除部分代碼後運行成功,就相應的能夠縮小排錯的範圍。

  1. MyBatis三大核心對象

SqlSessionFactory相似於JPA的EntityManagerFactory,Hibernate的SessionFactory

SqlSession 相似於JPA的EntityManager,Hibernate的Session

詳細的認識一下MyBatis的幾個核心類:

7.1.  SqlSessionFactoryBuilder

建造者模式:咱們最後拿到的這個對象是很是複雜的. 用這個建造者就它先爲咱們把這些複雜的代碼完成.

  這個類能夠被實例化,使用和丟棄。一旦你建立了SqlSessionFactory後,這個SqlSessionFactoryBuilder類就不須要存在了。所以SqlSessionFactoryBuilder實例的最佳範圍是方法範圍(也就是本地方法變量)。

你能夠重用SqlSessionFactoryBuilder來建立多個SqlSessionFactory實例,可是最好的方式是

不須要保持它一直存在來保證全部XML解析資源,由於還有更重要的事情要作。

7.2.  SqlSessionFactory

 一旦被建立,SqlSessionFactory應該在你的應用執行期間都存在。沒有理由來處理或從新建立它。使用SqlSessionFactory的最佳實踐是在應用運行期間不要重複建立屢次。這樣的操做將被視爲是很是糟糕的。所以SqlSessionFactory的最佳範圍是應用範圍。

有不少方法能夠作到,最簡單的就是使用單例模式或者靜態單例模式。然而這兩種方法都不認爲是最佳實踐。這樣的話,你能夠考慮依賴注入容器,好比Google Guice或Spring。這樣的框架容許你建立支持程序來管理單例SqlSessionFactory的生命週期。

7.3.  SqlSession

每一個線程都應該有它本身的SqlSession實例。SqlSession的實例不能被共享,也是線程不安全的。所以最佳的範圍是請求或方法範圍。

絕對不能將SqlSession實例的引用放在一個類的靜態字段甚至是實例字段中。

也毫不能將SqlSession實例的引用放在任何類型的管理範圍中,好比Serlvet架構中的HttpSession。

若是你如今正用任意的Web框架,要考慮SqlSession放在一個和HTTP請求對象類似的範圍內。換句話說,基於收到的HTTP請求,你能夠打開了一個SqlSession,而後返回響應,就能夠關閉它了。關閉Session很重要,

爲何在這裏咱們要先說這三大核心對象呢,由於在咱們必須要了解這三個對象的特性。才能夠更好的根據這個特性來完成工具類代碼。

  1. MyBatis的使用細節

8.1.  添加時拿到返回的主鍵

注:如果忘了爲何要拿到主鍵。能夠去看JDBC次日的課程,那裏我們當時有詳細的解釋。

 

         <!--

                  parameterType:須要傳入咱們的對象

                  useGeneratedKeys: 是否須要主鍵

                  keyColumn:主鍵所在的列,能夠不用配置

                  keyProperty:對象中的屬性(表明主鍵的那個屬性)

          -->

         <insert id="save" parameterType="cn.itsource.domain.Product"

                           useGeneratedKeys="true"

                           keyColumn="id"

                           keyProperty="id"

                  >

                  insert into product (productName,dir_id,salePrice,supplier,brand,cutoff,costPrice)

                           values (#{productName},#{dir_id},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})

         </insert>

主鍵就直接放到返回的對象裏面

8.2.  Log4j日誌框架

在使用MyBatis的不少時候,咱們須要把日誌打印出來,幫助咱們進行分析與排錯。特別是你們如今學習階段,要求你們都MyBatis的日誌打開。

打開後咱們能夠看到執行的SQL語句,能夠看到咱們傳遞的參數。

而MyBatis中打印日誌使用的是Log4j

8.2.1.   Log4j簡介:

Log4j有三個主要的組件:Loggers(記錄器),Appenders (輸出源)和Layouts(佈局)。

可簡單理解爲日誌類別,日誌要輸出的地方和日誌以何種形式輸出。綜合使用這三個組件能夠輕鬆地記錄信息的類型和級別,並能夠在運行時控制日誌輸出的樣式和位置。

8.2.2.   日誌等級

等級從低到高

TRACE:詳細

Debug:調試,相似於System.out.print

Info:信息,相似於JPA打印sql等級

Warn:警告,程序能夠正常運行,出現提示

Error:錯誤,出現異常

8.2.3.   log4j.properties

要在項目中打開日誌,你們在資源文件根目錄下建立一個log4j.properties的文件,並把下面的代碼拷備到裏面。

log4j.properties(日誌文件:)

log4j.rootLogger=ERROR, stdout

#log4j.rootLogger=NONE

log4j.logger.cn.itsource=TRACE   把左邊包名改爲你本身的包名

 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

注意:在上面的標紅部分是咱們須要修改的,它大概表示爲當前會打印哪些位置下面文件的日誌。

cn.itsource:必定要根據本身的包名狀況進行修改

    若是配置成功,那麼在MyBatis運行操做數據時就能夠看到相應的日誌了。

8.3.  MyBatis中爲一個類取別名

別名:分兩種

8.3.1.   內置別名

 

8.3.2.   自定義別名

在咱們前面傳參與接收結果的時候,我們一直是使用的全限定名。

可是MyBatis本身在使用不少類型的時候(如Integer,Boolean)卻能夠直接使用別名。

那麼,我們本身的寫的類能不能使用別名呢?

你們能夠直接找到官文文檔上typeAliases這一章,有介紹咱們怎麼爲本身的類取別名。

取別名有什麼用,呵呵。我認識一個朋友,他叫作:特雷西.麥克格雷迪,我叫他麥迪

 

下面爲取別名的代碼:

<typeAliases>

                  <!--

                           將一個包下面的全部類都取上別名:<package name="cn.itsource.domain" />

                           alias:取的別名

                           type:這個別名所對應的Java類

                                    :別名使用的時候與大小寫無關

                   -->

<typeAlias alias="product" type="cn.itsource.domain.Product" />

<!-- 作項目的時候使用 -->

<package name="cn.itsource.mybatis.day1._2_detail" />

</typeAliases>

 

注:必需在主文件中設置別名,其它地方纔可使用(切記切記)

8.4.  列名與屬性名不對應的解決方案resultMap

    原來經過javaBean自動映射,可使用手動映射

你們應該有注意到,前面我們作映射文件的時候,只作了表與對象之間的聯繫。並無作列與字段之間的聯繫。那麼它們之間是怎麼聯繫上的呢?

因爲以前我們的列名與屬性名是同樣的,所以框架進行了自動的識別。

那麼:若是我們的列名與屬性名不一致了(對應不上),這時候應該怎麼辦呢?

這時候,就須要咱們開發人員告訴MyBatis,咱們須要把哪些列名與屬性名對應上。

 

在MyBatis中,提供了一個resultMap的標籤,就是讓我們來完成返回結果的關係對應的,使用方式以下:

 

<!--

         返回的數據映射

                  type:表明是要映射的對象

                  id:表明惟一(過會咱們要拿到它)

-->

<resultMap type="cn.itsource.domain.Product" id="productMap">

         <!--

                  column:對應的列名

                  property:對應的屬性名

          -->

         <id column="id" property="id"  />

         <result column="productName" property="name" />

</resultMap>     

 

<select id="queryOne" parameterType="long" resultMap="productMap">

         select * from product where id = #{id}

</select>

  1. 課程總結

9.1.  重點

  1. MyBatis CRUD

9.2.  難點

  1. 怎樣獲取主鍵,怎樣配置
  2. Log4j理解
  3. 別名
  4. 常見異常
  5. java.lang.ClassNotFoundException: Cannot find class: id

<delete id="delete" parameterType="id">應該傳入long類型,而不是id

  1. Caused by: org.xml.sax.SAXParseException; lineNumber: 23; columnNumber: 4; 元素類型 "select" 必須由匹配的結束標記 "</select>" 終止。

<select id="getAll" resultType="cn.itsource.mybatis.day1._1_hello.Product">

         select id,productName,salePrice,costPrice,cutoff,supplier,brand,dir_id from

         product

</insert>

  1. Caused by: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.itsource.mybatis.day1._1_hello.ProductMapper.get

沒有配置文件裏面加載映射文件,如何開始就使用

  1. Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'productName' in 'class cn.itsource.mybatis.day1._2_detail.Product'

Product類裏面沒有'productName'屬性

  1. 常見問題
  2. 沒有導入數據庫的驅動包
  3. 在XML中不少都是字符串,細心,不要寫錯
  4. 在映射文件中全限定類名可能會寫錯
  5. 找不到相應的Statement(sql語句)
  6. 找SQL的Statement寫錯了
  7. 在覈心XML中沒有找相應的映射文件
  8. 在咱們調用Statement(sql語句的時候),常常會忘記傳參
  9. 執行成功後,數據庫卻沒有反映,頗有多是沒有提交事務
  10. 可能咱們忘了寫執行的代碼了
  11. 錯誤必定要打印出來(執行的時候沒效果,可是又不報錯)
  12. Mapper中就算一個語句沒有使用,它的錯也可能會影響到其它正確的語句
  13. 框架的錯每每從後向前找
  14. 不少同窗沒有取別名,可是他一直去用
  15. Mysql亂碼,添加字符編碼:useUnicode=true&amp;characterEncoding=UTF-8

 

  1. 課後練習
  2. 面試題
  3. mybatis相較於jdbc的優勢?

把sql語句從java代碼中抽取出來,方便維護。而且修改sql時不用修改java代碼

不用手動設置參數和對結果集的處理。

  1. 擴展知識或課外閱讀推薦

14.1.         擴展知識

  1. 之後工做是用JPA(Hibernate)仍是用MyBatis呢?

 

  1. MyBatis與JPA(Hibernate)的區別?
相關文章
相關標籤/搜索