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(資料來源)
- environment(環境變數)
- 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
,他下面有兩個子標籤,分別是 mapper
和 package
對映方法如下:
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 | 生成有參構造方法 |