1. 程式人生 > 實用技巧 >JS 頁面生成錨點

JS 頁面生成錨點

MyBatis 是基於 Java 語言的開源的持久層框架,利用實體類和資料表之間產生了關聯,通過對映檔案中的 sql 語句對資料庫進行操作

使用 maven 建立工程需要匯入 mybatis 的依賴:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.5</version>
</dependency>

簡單例項演示

mybatis的持久層開發有兩種方式,一種是原始的 dao 開發,比較繁瑣,還有一種是基於介面的 JDK 動態代理開發,也是最普遍的一種開發模式

原始dao開發模式

使用原始 dao 開發模式,首先第一步: 建立 mybatis 的核心配置檔案,一般取名為 mybatis-config.xml

在dataSource標籤中配置資料庫連線,在mapper標籤中配置xml對映檔案目錄,然後去書寫xml對映檔案

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <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:///test"/>
                <property name="username" value="root"/>
                <property name="password" value="zhang"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/beanMapper.xml"/>
    </mappers>
</configuration>

第二步:在上面的對映檔案目錄對應的位置建立檔案

mapper 標籤的 namespace 屬性自定義書寫,select 標籤的 id 不能與其他 id 重複,resultType 是和資料庫表對應的實體類的全限定路徑名,實體類僅僅只有和表中欄位對應的屬性及 get set toString 方法而已

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test1">
    <select id="findAll" resultType="club.hanzhe.bean.Bean">
        select * from test1
    </select>
</mapper>

第三步:建立dao類,通過dao介面類來操作 mapper 檔案中的增刪改查

dao類想要操作mapper檔案需要使用工廠物件,工廠物件暫時就不在這裡建立了,由呼叫者給他物件讓他使用就行

操作mapper檔案需要使用mapper檔案的 namespace.標籤id,例如 test1.findAll

public class BeanDao {
    private SqlSessionFactory factory ;
    public BeanDao( SqlSessionFactory factory ){
        this.factory = factory;
    }
    public List<Bean> findAll(){
        SqlSession sqlSession = factory.openSession();
        List<Bean> list = sqlSession.selectList("test1.findAll");
        return list;
    }
}

第四步:建立測試類,對寫好的程式碼進行測試

因為呼叫一個dao都會使用一個工廠物件,所以這裡就直接建立一個供所有dao使用,節省資源

public class AppTest {
    private static InputStream is = null;
    private static SqlSessionFactory factory = null;
    @Before
    public void before(){
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
        } catch (Exception e) {
            System.out.println("獲取配置檔案失敗!");
        }
        factory = new SqlSessionFactoryBuilder().build(is);
    }
    @Test
    public void tes1(){
        BeanDao dao = new BeanDao(factory);
        List<Bean> list = dao.findAll();
        for (Bean bean : list)
            System.out.println(bean);
    }
}

基於介面的動態代理開發

使用動態代理開發模式,首先第一步: 建立 mybatis 的核心配置檔案,一般取名為 mybatis-config.xml

這裡和 dao 開發的配置檔案一模一樣,可以去上面 copy

第二步:在上面的對映檔案目錄對應的位置建立對映檔案

這裡和上面幾乎一模一樣,但是動態代理的 mapper 的 namespace 指向的必須是介面的全限定名稱

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="club.hanzhe.dao.BeanDao">
    <select id="findAll" resultType="club.hanzhe.bean.Bean">
        select * from test1
    </select>
</mapper>

第三步:按照上面對映檔案目錄建立介面

這裡和上面不同的是不需要太多繁瑣的結構,只需要建立一個方法即可對應mapper中的增刪改查,但是需要注意一點:介面方法名必須和mapper的CRUD標籤id一致,否則會報錯

public interface BeanDao {
    List<Bean> findAll();
}

第四步:建立測試類,對寫好的程式碼進行測試

public class TestDemo {
    private SqlSessionFactory factory = null;
    @Before
    public void before(){
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
        }catch (Exception e){
            System.out.println("載入核心配置檔案失敗");
            System.exit(0);
        }
        this.factory = new SqlSessionFactoryBuilder().build(is);
    }
    @Test
    public void test1(){
        SqlSession session = factory.openSession();
        BeanDao mapper = session.getMapper(BeanDao.class);
        List<Bean> list = mapper.findAll();
        for (Bean bean : list)
            System.out.println(bean);
    }
}

注意:在 openSession 的時候是可以傳入一個 boolean 引數的,如果不傳引數預設為 false,如果要執行 DML 語句進行增刪改的話,一定要傳入 true 做為引數,否則他不會自動提交 ( 你可以手動提交 ),查詢無需提交所以不需要設定

Mybatis 的核心配置檔案

mybatis 的核心配置檔案,一般都起名為 mybatis-config.xml 或者是 sqlMapConfig.xml ,在核心配置檔案中可以通過某些標籤對 mybatis 進行一些配置

注意:mybatis 的核心配置檔案內不可以書寫中文註釋 (英文或數字可以),否則報錯

mybatis 提供了很多標籤進行配置,但是這些標籤也有著先後順序,如果標籤不按順序書寫也是會報錯的

  • configuration(配置檔案的根標籤)
    • properties(屬性)
    • settings(設定)
    • typeAliases(類型別名)
    • typeHandlers(型別處理器)
    • objectFactory(物件工廠)
    • plugins(外掛)
    • environments(環境配置)
      • environment(環境變數)
        • transactionManager(事務管理器)
        • dataSource(資料來源)
    • databaseIdProvider(資料庫廠商標識)
    • mappers(對映器)

上面來自 mybatis 官方文件,這裡會挑常用的標籤進行筆記

Environments 環境配置

1. 環境的選擇

在 mybatis 配置檔案中使用 environments 標籤配置環境,在他下面可以有一個或多個 environment 子標籤,每個都代表一個環境,然後在 environments 標籤中使用 default 屬性對環境進行選擇

這裡使用 default 對環境進行選擇,目前選擇的是MySQL的環境

<environments default="mysql">
    <environment id="mysql">
        這是MySQL的環境
    </environment>
    <environment id="oracle">
        這是oracle的環境
    </environment>
</environments>

除開配置檔案內的預設環境,也可以在開啟開啟會話工廠的時候傳入指定環境的id進行選擇環境

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is, "mysql");

注意: 儘管可以配置多個環境,但每個 SqlSessionFactory 例項只能選擇一種環境。

2. 事務管理器

在每個 environment 子標籤環境中有 transactionManager 標籤的 type 屬性可以對 SQL 進行事務控制管理,管理事務的管理器有兩種:【 JDBC 】【 MANAGED 】

事務管理器 說明
JDBC 直接使用了 JDBC 的提交和回滾設定,它依賴於從資料來源得到的連線來管理事務作用域。
MANAGED 什麼都不做,讓容器來管理事務的整個生命週期,不建議使用

建議使用 JDBC 來管理事務

<environment id="mysql">
    <transactionManager type="JDBC"/>
</environment>

3. 資料來源

資料來源是配置 mybatis 和資料庫進行連線的相關配置,他由 environment 標籤下的 dataSource 標籤進行設定

通過 dataSource 標籤的 type 屬性可以選擇資料來源型別:

型別 說明
UNPOOLED 只是每次被請求時開啟和關閉連線,反應較慢,適用於簡單小型專案
POOLED 相對於UNPOOLED相比使用了 資料庫連線池 的感念
JNDI 能在如 EJB 或應用伺服器這類容器中使用

資料來源最基本的四個屬性:

  • 【driver】 資料庫連線驅動類
  • 【url】 資料庫連結地址
  • 【username】 使用者名稱
  • 【password】 密碼

最常見的 environments 標籤配置

<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:///test"/>
            <property name="username" value="root"/>
            <property name="password" value="******"/>
        </dataSource>
    </environment>
</environments>

Mappers 對映標籤

書寫的 mapper 檔案需要被對映到核心配置檔案中,對映的標籤就是 mappers ,他下面有兩個子標籤,分別是 mapperpackage 對映方法如下:

1. 對映的檔案在resources目錄下

<mappers>
    <!-- 對映單個檔案 -->
    <mapper resource="beanMapper.xml"/>>
    <!-- 使用 * 萬用字元對映多個檔案 -->
    <mapper resource="*Mapper.xml"/>
</mappers>

2. 對映的檔案在dao包下

當 mapper 檔案在 dao 包下的時,mapper 和介面必須是同名的,或者在 resources 目錄下有著同級的目錄

<mappers>
    <!-- 對映單個檔案 -->
    <mapper class="club.hanzhe.dao.BeanDao" />
    <!-- 對映多個檔案 -->
    <package name="club.hanzhe.dao"/>
</mappers>

3. 介面註解開發

<mappers>
    <package name="club.hanzhe.dao"/>
</mappers>

注意!當mapper檔案在dao包下的時候,需要在maven的pom檔案中新增如下程式碼,否則xml檔案可能不會被打包釋出

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

Properties 屬性

我們在使用傳統 JDBC 的時候都會把 driver,url 等等放在一個 propertis 字尾的檔案中,這樣可以降低程式碼的耦合性,方便環境切換,mybatis 中也支援這種做法,使用 properties 標籤就可以實現

1. 手寫 properties 配置檔案

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1/庫名
username=root
password=*****

2. 使用 properties 標籤將配置檔案引入進來

<!-- 使用該標籤將配置檔案引入進來,然後就可以使用 ${} 符號來呼叫配置檔案內的值了 -->
<properties resource="db.properties" />
<!-- 例如: -->
<property name="driver" value="${driver}">

TypeAliases 別名

在我們的 mapper 對映檔案中,CRUD 標籤中的引數,返回結果 resultType 通常都是全限定名,例如:

<select id="findAll" resultType="club.hanzhe.bean.Bean"></select>

這個時候我們就可以使用 typeAliases 標籤下的 typeAlias 子標籤配置類別名,可以簡化全限定名書寫格式

abc就是這個類的類別名,就可以在對映檔案中使用了

<typeAliases>
    <typeAlias type="club.hanzhe.bean.Bean" alias="abc" />
</typeAliases>

<select id="findAll" resultType="abc"></select>

typeAlias 標籤中的 alias 屬性也可以忽略不寫,預設已類名作為別名 (別名首字母小寫即可)

<typeAliases>
    <typeAlias type="club.hanzhe.bean.Bean" />
</typeAliases>

<select id="findAll" resultType="bean"></select>

但如果是個較大的專案,表和實體類比較多,如果逐個實體類配置的話會很麻煩,這時可以使用 package 子標籤

將指定包下的所有類全部配置別名,別名為類本身名字 (首字母小寫)

<typeAliases>
    <package name="club.hanzhe.bean" />
</typeAliases>

<select id="findAll" resultType="bean"></select>

Settings 全域性設定

在 mybatis 中可以對全域性進行一些設定,設定需要用 settings 下的 setting 子標籤實現,格式體現為:

<settings>
  <setting name="設定名稱" value="對應引數值"/>
</settings>

常用的設定有:

設定名 作用描述 引數
cacheEnabled 設定全域性快取的開啟和關閉 boolean
defaultStatementTimeout 設定超時時間,它決定驅動等待資料庫響應的秒數。 任意正整數
mapUnderscoreToCamelCase 是否開啟駝峰命名規則 boolean
logImpl 配置日誌資訊,個人推薦使用 STDOUT_LOGGING 日誌 @官方文件

Mapper 對映檔案

mapper 對映檔案,用來負責和資料庫互動的 sql 程式碼,主要是增刪改查四個標籤為主:

增刪改標籤

增刪改標籤是用來書寫插入 sql 的標籤,比較常用的幾個屬性如下:

<insert
	id="addBean"
	parameterType="club.hanzhe.bean"
	flushCache="true"
	timeout="20">
屬性 作用
id 用來作為標籤的識別符號,使用id可以直接找到當前標籤呼叫
parameterType 接受的引數的型別,如果引數型別是集合,那麼就填集合內元素的型別
flushCache 增刪改標籤預設設定為true,只要語句被呼叫,就會清空本地和二級快取
timeout 丟擲異常之前,驅動程式等待響應的時間,預設為空值

查詢標籤

select 標籤是用來專門書寫查詢語句的標籤,比較常用的幾個屬性如下:

<select
    id="selectPerson"
    parameterType="int"
    resultType="hashmap"
    resultMap="personResultMap"
    flushCache="false"
    useCache="true"
    timeout="10"
    fetchSize="256"
    statementType="PREPARED"
    resultSetType="FORWARD_ONLY">

除開增刪改相同的屬性之外,查詢有著自己的屬性

屬性 作用
resultType 用來設定查詢返回的資料對應的實體類
resultMap 屬於高階的parameterType,他可以手動配置實體類屬性和資料庫欄位的對映
useCache select 預設為 true,執行查詢後將查詢結果快取在二級快取中

新增時返回 ID

這裡記一個十分好用的小功能,當我們執行 insert 之後,想要立刻操作這行記錄,但是他的主鍵是自增的,我們想要操作他需要獲取他的 ID,這個時候我們可以通過屬性設定回顯 ID

假設當前有一個 bean,屬性為 userid,username,password

<!-- useGeneratedKeys="true" 取出資料庫內自動生成的主鍵 -->
<!-- keyProperty="userid" 將主鍵設定在 bean 中的某個屬性上 -->
<insert id="addUser" parameterType="user" useGeneratedKeys="true"keyProperty="userid">
	insert into t_user values(#{username}, #{password})
</insert>
@Test
public void test(){
    User user = new User();
    user.setUsername("張");
    user.setPassword("123");
    userDao.addUser(user);
    // 當我們執行插入語句後,如果正常執行,那麼userid就會成功賦值
    System.out.println(user.getUserid());
}

SQL 程式碼片段

可以被用來定義可重用的 SQL 程式碼段,例如:

定義了 id 為 t_user 的 sql 程式碼片段,在下面的增刪改查中就可以使用 include 來呼叫了

<sql id="t_user">userid, username, usersex, usertel</sql>

<select id="selectAll" resultType="user">
    SELECT <include refid="t_user" /> FROM t_user
</select>

${ } 和 #{ } 的區別

${ }和#{ }他們都是用來接收傳入引數的,只不過有些細節需要留意,假設現在有一行SQL語句:

select * from t_user where userid = 1;

其中作為查詢條件的 1 是需要接收傳入引數的,那麼獲取到傳入引數有兩種方法:

  • ${ },拼接SQL字串
  • #{ },作為SQL佔位符

如果使用 ${} 的話,通過日誌可以看到,它以拼接字串的方式執行,這樣的話就很容易收到SQL注入的攻擊

select * from t_user where userid = 1;

但是如果使用 #{} 的話,他是將 SQL 程式碼預處理之後在執行之前進行引數替換,傳入的引數都將作為普通引數對待,通過執行日誌就可以看到:

select * from t_user where userid = ? ;

這是二者最明顯的差距,通過佔位符可以有效防止SQL注入攻擊,推薦使用#{ }

ResultMap 標籤

一般使用 resultType 返回物件的時候,是資料庫自動檢測實體類中和欄位匹配的屬性進行封裝,但是如果實體類中的屬性和表中的欄位截然不同的話,就需要手動配置他們之間的對映關係了

<!-- 
  id:為當前標籤的命名,會在select標籤中的返回型別中用到
  type:為返回的主類的型別,Student中包含Score型別的變數,所以Sutdent是主類
  extends:繼承,將指定的resultMap的id作為值放在這裡,會繼承之前書寫的對映
  autoMapper:為其他屬性自動匹配的開關,預設為false關閉狀態
   為false時,只有手動配置的對映會匹配成功,未設定的為null值
   為true時,將按照手動配置的進行匹配,沒有手動配置的會自動按照變數名匹配
-->
<resultMap id="map1" type="club.hanzhe.pojo.U_T">
    <!--
       id標籤為設定當前主類與資料表中對應表的主鍵的匹配
       column:資料表中的欄位
       property:與該欄位對應的本類中的屬性
     -->
    <id column="rowNo" property="rowNo" />
    <!--
   result標籤為設定當前主類與資料表中對應表的其他欄位的匹配
   column:資料表中的欄位
   property:與該欄位對應的本類中的屬性
  -->
    <result column="u_id" property="userid" />
    <!--
   association標籤為設定當前主類中對映的其他類
   property:類中的屬性
   javaType:屬性所對應的那個類的全限定名,可以使用別名
   autoMapping:自動匹配表中的其他欄位和類中的屬性
  -->
    <association property="tel" javaType="club.hanzhe.pojo.Tel">
        <id column="t_id" property="telid" />
    </association>
    <!--
   collection用來對映集合,多用於一對多查詢 
   與association的唯一差別就是javaType變成了ofType 
  -->
    <collection property="tel" ofType="club.hanzhe.pojo.Tel">
        <id column="t_id" property="telid" />
    </collection>
</resultMap>

動態 SQL

通過傳入的引數對 sql 進行靈活化使用,類似 Java 一樣,通過 判斷迴圈 來控制 SQL 的最終執行

if 判斷標籤

如果接收的username引數不為空的話,就追加當前標籤內的sql語句

<select id="findBean" resultType="bean">
    select * from test
    <if test="id != null and id != ''">
        where id = #{id}
    </if>
</select>

where 過濾標籤

使用 where 標籤之後,如果 where 內有符合 if 條件的會自動新增 where 關鍵字,如果沒有符合的就不新增

如果有多個 if 符合條件,需要在前面加上 and 或者 or 等判斷條件,如果是第一個成立的條件會預設省略前面的 and 或 or,後續的會新增

<select id="findUser" resultType="user">
    select * from t_user
    <where>
        <if test="userid != null">
            and userid = #{userid }
        </if>
        <if test="username != null">
            and username like #{username }
        </if>
        <if test="usersex != null">
            and usersex = #{usersex }
        </if>
        <if test="usertel!= null">
            and usertel = #{usertel }
        </if>
    </where>
</select>

choose 標籤

choose 標籤有著和 switch 類似的功能,他要求當前判斷至少成立一個才可以結束,如果沒有成立的會執行otherwise

<choose>
    <when test=""></when>
    <when test=""></when>
    <otherwise></otherwise>
</choose>

set 標籤

使用 set 標籤之後,如果 set 內有符合 if 條件的會自動新增 set 關鍵字,如果沒有符合的就不新增,需要注意一點的是,set → if 內的 sql 結尾一定要帶上逗號,系統會自動省略但不會自動追加。

<update id="updateUser" parameterType="user" >
    update t_user
    <set>
        <if test="username != null and username != ''">
            username = #{username },
        </if>
        <if test="usersex != null and usersex != ''">
            usersex = #{usersex },
        </if>
        <if test="usertel != null and usertel != ''">
            usertel = #{usertel },
        </if>
    </set>
    where userid = #{userid }
</update>

foreach 標籤

foreach 標籤用來遍歷傳進來的集合或陣列容器,多用於批量刪除操作,裡面的屬性解釋如下:

<delete id="find1">
	delete from bean where id in
	<foreach collection="list" open="(" close=")" separator=", " item="i">
		#{ i }
	</foreach>
</delete>
  • collection:傳進來被遍歷的那個容器的名字,可以是陣列或集合
  • open:迴圈開始前需要新增的字首
  • close:迴圈結束後需要新增的後置
  • separator:每迴圈一次時需要在中間新增的分隔符
  • item:被迴圈出來的每個欄位,在標籤內直接使用即可

cache 快取標籤

一級快取

在 mybatis 中一級快取是預設開啟的,在進行 openSession 的時候就自動打開了一級快取,且對於一級快取的操作,只能清空,不能禁用,一級快取的作用範圍是當前的 SqlSession 例項

在同一個 SqlSession 例項中,兩次同樣的查詢返回的結果是一致的,但是如果是兩個SqlSession那麼進行相同的查詢結果就會不同,這裡就不寫了

public void test4(){
    SqlSession session = this.factory.openSession(true);
    BeanDao mapper = session.getMapper(BeanDao.class);
    Bean bean1 = mapper.findById(7844);
    Bean bean2 = mapper.findById(7844);
    System.out.println(bean1 == bean2);
}
二級快取

二級快取的範圍是基於當前的 mapper.xml 配置檔案的 mapper 標籤,也就是當前的 namespace 下,一個二級快取可以橫跨多個一級快取,而二級快取預設是關閉的,開啟二級快取的方法就是使用 cache標籤

沒錯,只要在 mapper 下面加上這麼一句程式碼,二級快取就開啟完成了,簡單粗暴

<cache />

在開啟二級快取後還不能立刻使用,會報錯,需要讓該 mapper 相關的所有 bean 實現 Serializable 序列化介面

Mybatis 註解開發

CRUD 註解

在 mybatis 中也可以不使用 mapper 對映檔案,改為使用註解開發,分別相對著增刪改查四個註解

@Insert("insert into t_user values(null,#{name},#{sex},#{address})")
public int saveUser(User user);

@Delete("DELETE FROM t_user WHERE u_id = #{abc}")
public int removeUser(Integer id);

@Update("update t_user set u_address=#{address} where u_name = #{name}")
public int updateUser(User user);

@Select("select * from t_user where u_id = #{abc}")
public User findUserById( Integer id );

注意!使用 mapper 檔案的時候需要掃描 mapper 檔案所在位置,然後才可以使用,使用註解開發也需要掃描:

將所有帶有註解的介面都掃描

<mappers>
    <package name="club.hanzhe.dao"/>
</mappers>

Result 註解

使用 xml 開發時,會遇到欄位與實體類屬性名不匹配造成封裝失敗的情況,起別名解決是一種方法,但是一般都使用 resultMap 結果對映,將欄位與屬性匹配,註解開發也可以使用 resultMap,對應的註解是 @Results

使用註解的方式匹配欄位與屬性查詢

@Results(
    id = "r1",	// id:給當前results起名字,像resultMap一樣繼承使用
    value = {	// value:配置多個對映
		/*
		 *  @Result中的屬性:
		 *  	id:表中的id列是否為主鍵,是為true,不寫預設為false
		 *  	column:表中的欄位
		 *  	property:表中欄位對應的pojo中的屬性
		 *  	只需要將不匹配的欄位屬性配上即可,匹配的可以省略不寫
		 */
        @Result( column = "u_id" , property = "id" ),
        @Result( column = "u_name" , property = "name" ),
        @Result( column = "u_sex" , property = "sex" ),
        @Result( column = "u_address" , property = "address" )
    }
)
public User findUserById( Integer id );

如果有另一個查詢與他的規則相同,那麼可以引用之前寫的Results的id屬性

@Select("select * from t_user where u_name = #{abc}")
@ResultMap("r1")
public User findUserByName( String name );

擴充套件功能

Mybatis 逆向工程

逆向工程是根據資料庫中表的資訊進行自動建立實體類,介面,對映檔案的技術

1. 環境配置

使用逆向工程必須引入他的依賴或jar包

<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.3.5</version>
</dependency>

2. 逆向工程配置檔案

你可以在任意位置 ( 包括專案外 ) 建立逆向工程所需要的配置檔案,需要手動配置的地方有以下幾點:

  • properties 標籤中的配置檔案需要自己書寫,也可以書寫該標籤及檔案
  • jdbcConnection 標籤需要修改,修改需參考上面的 properties 配置檔案
  • javaModelGenerator 標籤需要修改,他是實體類生成的目標包路徑
  • sqlMapGenerator 標籤需要修改,他是 mapper 對映檔案生成的目標路徑
  • javaClientGenerator 標籤需要修改,他是介面生成的目標包路徑
  • table 標籤的 tableName 屬性需要修改,他是逆向工程所參考的資料表
    • 如有多個表被參考就書寫多個 table 標籤,可以直接複製修改 tableName 屬性
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <properties resource="db.properties"></properties>
    <context id="testTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!--是否去除自動生成的註釋 true是:false 否-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--資料庫連線-->
        <jdbcConnection driverClass="${driver}" connectionURL="${url}" userId="${username}" password="${password}"></jdbcConnection>
        <!-- 預設false,把JDBC DECIMAL 和 NUMERIC 型別解析為 Integer,為 true時把JDBC DECIMAL和NUMERIC型別解析為java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!--生成的實體類存放的位置-->
        <javaModelGenerator targetProject="src/main/java" targetPackage="club.hanzhe.bean">
            <!--enableSubPackages,是否讓schema作為包的字尾-->
            <property name="enableSubPackages" value="false"/>
            <!--從資料庫返回的值被清除前後空格-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!--mapper對映檔案存放的位置-->
        <sqlMapGenerator targetProject="src/main/resources" targetPackage="mappers">
            <property name="enableSubPackages" value="false"></property>
        </sqlMapGenerator>
        <!--targetPackage:mapper介面生成的位置-->
        <javaClientGenerator type="XMLMAPPER" targetProject="src/main/java" targetPackage="club.hanzhe.dao">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
        <!--tableName為逆向工程針對的表的表名,可以萬用字元匹配所有表,剩下的屬性統統false-->
        <table tableName="%"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false"></table>
    </context>
</generatorConfiguration>

3. 使用逆向工程

在環境配置完成後使用下面這段模板程式碼,執行後就會將實體類,介面,mapper檔案自動生成

需要在改程式碼中手動設定配置檔案的檔名及位置

import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Generator {
    @Test
    public void create(){
        try {
            List<String> warnings = new ArrayList();
            boolean overWriter = true;
            // 這裡載入剛剛建立的逆向工程配置檔案
            File configFile = new File("檔案位於磁碟的絕對路徑");
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config = cp.parseConfiguration(configFile);
            DefaultShellCallback callback = new DefaultShellCallback(overWriter);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            myBatisGenerator.generate(null);
        }catch (Exception e){
            System.out.println("操作失敗!");
            System.out.println("==================================================");
            System.out.println(e);
            e.printStackTrace();
        }
    }
}

PageHelper 分頁外掛

pageHelper 外掛是針對 mybatis 設計的一款分頁外掛,通過攔截器對 sql 進行操作,使其擁有分頁的能力

1. 環境配置

使用 pageHelper 分頁外掛需要匯入他的 maven 依賴或者匯入他的 jar 包

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <!-- 可以官網查詢最新版 -->
    <version>5.0.0</version>
</dependency>

在 maven 依賴新增完成後,還需要在 mybatis 的核心配置檔案中使用 plugins 標籤註冊 pageHelper 外掛

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

2. 使用PageHelper

PageHelper 依賴引入後,在程式中就有了 PageHelper 類,呼叫它的 startPage 靜態方法,後緊跟的第一條查詢語句就是分頁查詢

startPage 的靜態方法需要兩個引數,第一個是查詢的頁碼,第二個是每頁的查詢數量

public void test1(){
    // 查詢第二頁,每頁5條記錄
    PageHelper.startPage(2, 5);
    List<Bean> list = mapper.findAll();
    for (Bean bean : list)
        System.out.println(bean);
    System.out.println(list);
}

分頁除了 PageHelper 類,還有一個 PageInfo 可以使用,將查詢的結果封裝到 PageInfo 中,可以查詢一些和分頁相關的資訊

public void test1(){
    SqlSession session = factory.openSession();
    BeanDao mapper = session.getMapper(BeanDao.class);
    PageHelper.startPage(2, 5, true);
    PageInfo info = new PageInfo(mapper.findAll());
    System.out.println("總頁碼:" + info.getPages());
    System.out.println("總記錄數:" + info.getTotal());
    System.out.println("結果集:");
    List<Bean> list = info.getList();
    for (Bean bean : list)
        System.out.println(bean);
}

3. PageInfo常用引數

在將結果集封裝到 PageInfo 中的時候,可以可選性的傳入一個導航頁碼的引數,可以獲取到和當前頁相鄰的頁碼

public void test1(){
    SqlSession session = factory.openSession();
    BeanDao mapper = session.getMapper(BeanDao.class);
    PageHelper.startPage(201, 5, true);
    // 在建立info物件的時候可以跟隨一個int型別,這個值是當前頁附近的頁碼的數量
    PageInfo info = new PageInfo(mapper.findAll(), 7);
    System.out.println("當前頁:" + info.getPageNum());
    System.out.println("每頁顯示數量:" + info.getPageSize());
    System.out.println("當前頁資訊:");
    for (Object obj : info.getList())
        System.out.println(obj);
    System.out.println("總頁碼:" + info.getPages());
    System.out.println("總記錄數:" + info.getTotal());
    System.out.println("上一頁:" + info.getPrePage());
    System.out.println("下一頁:" + info.getNextPage());
    System.out.println("是否首頁:" + info.isIsFirstPage());
    System.out.println("是否尾頁:" + info.isIsLastPage());
    System.out.println("導航條頁碼:");
    for (int page : info.getNavigatepageNums() )
        System.out.print( page + "  " );
    System.out.println("\n導航條中首頁" + info.getNavigateFirstPage());
    System.out.println("導航條中尾頁" + info.getNavigateLastPage());
}
  • 這裡需要注意!每頁顯示數量是指分頁是設定的數量,例如設定每頁只顯示5條,獲取到的就是5,而不是最後一頁只顯示三條就返回三,這是錯誤的

合理化查詢

在網頁中往往有些人會鑽空子亂改資料,例如只有20頁資料,他修改了引數請求到了第50頁,這種情況經常會發生,所以在註冊 pageHelper 的時候可以新增一個引數使資料變得合理化

<plugin interceptor="com.github.pagehelper.PageInterceptor">
    <property name="reasonable" value="true" />
</plugin>

Lombok 外掛

在我們進行查詢的時候,需要將查詢的結果封裝到指定的實體類中,而對應的例項類需要書寫響應的 get set 方法,構造方法及 toString 方法,這樣比較麻煩,這是可以使用 lombok 外掛進行自動生成功能

1. 環境配置

使用 lombok 需要引入他的 maven 依賴

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
</dependency>

在依賴引入後還需要在編輯器中安裝 lombok 的外掛 ( IDEA 編輯器為例 ) File → settings → plugins → install JetBrains plugin... 在裡面搜尋 lombok 下載安裝,而後在 file → settings → build,Exe.. → Compiler → Annotation Pro... 裡面選中當前專案,在右面的 Enable annotation processing 選項打勾

2. 使用 Lombok 外掛

在目標實體類上,只需要書寫好屬性即可,無需書寫其他多餘方法,使用 lombok 提供的註解用來一鍵生成:

註解 作用
@Get 一鍵生成所有 get 方法
@Set 一鍵生成所有 set 方法
@ToString 一鍵生成 toString 方法
@Data 一鍵生成 get set toString 等方法
@NoArgsConstructor 生成無參構造方法
@AllArgsConstructor 生成有參構造方法