本系列文章Github 後端進階指南 已收錄,此專案正在完善中,歡迎star。
1. Mybatis的開發方式
此處使用的是JDK的動態代理方式,延遲載入使用的cglib動態代理方式
1.1 代理理解
代理分為靜態代理和動態代理。此處先不說靜態代理,因為Mybatis中使用的代理方式是動態代理。
動態代理分為兩種方式:
- 基於JDK的動態代理--針對有介面的類進行動態代理
- 基於CGLIB的動態代理--通過子類繼承父類的方式去進行代理。
1.2 XML方式
開發方式
只需要開發Mapper介面(dao介面)和Mapper對映檔案,不需要編寫實現類。
開發規範
Mapper介面開發方式需要遵循以下規範:
1、 Mapper介面的類路徑與Mapper.xml檔案中的namespace相同。
2、 Mapper介面方法名稱和Mapper.xml中定義的每個statement的id相同。
3、 Mapper介面方法的輸入引數型別和mapper.xml中定義的每個sql 的parameterType的型別相同。
4、 Mapper介面方法的返回值型別和mapper.xml中定義的每個sql的resultType的型別相同。
mapper對映檔案
<?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.kkb.mybatis.mapper.UserMapper">
<!-- 根據id獲取使用者資訊 -->
<select id="findUserById" parameterType="int" resultType="com.kkb.mybatis.po.User">
select * from user where id = #{id}
</select>
</mapper>
複製程式碼
- mapper介面
/**
* 使用者管理mapper
*/
public interface UserMapper {
//根據使用者id查詢使用者資訊
public User findUserById(int id) throws Exception;
}
複製程式碼
- 全域性配置檔案中載入對映檔案
<!-- 載入對映檔案 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
複製程式碼
- 測試程式碼
public class UserMapperTest{
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
//mybatis配置檔案
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//使用SqlSessionFactoryBuilder建立sessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
//獲取session
SqlSession session = sqlSessionFactory.openSession();
//獲取mapper介面的代理物件
UserMapper userMapper = session.getMapper(UserMapper.class);
//呼叫代理物件方法
User user = userMapper.findUserById(1);
System.out.println(user);
//關閉session
session.close();
}
}
複製程式碼
1.3 註解方式
開發方式
只需要編寫mapper介面檔案介面。
mapper介面
public interface AnnotationUserMapper {
// 查詢
@Select("SELECT * FROM user WHERE id = #{id}")
public User findUserById(int id);
// 模糊查詢使用者列表
@Select("SELECT * FROM user WHERE username LIKE '%${value}%'")
public List<User> findUserList(String username);
// 新增並實現主鍵返回
@Insert("INSERT INTO user (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})")
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", resultType = int.class, before = false)
public void insertUser(User user);
}
複製程式碼
- 測試程式碼
public class AnnotationUserMapperTest {
private SqlSessionFactory sqlSessionFactory;
/**
* @Before註解的方法會在@Test註解的方法之前執行
*
* @throws Exception
*/
@Before
public void init() throws Exception {
// 指定全域性配置檔案路徑
String resource = "SqlMapConfig.xml";
// 載入資原始檔(全域性配置檔案和對映檔案)
InputStream inputStream = Resources.getResourceAsStream(resource);
// 還有構建者模式,去建立SqlSessionFactory物件
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
}
@Test
public void testFindUserList() {
SqlSession sqlSession = sqlSessionFactory.openSession();
AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);
List<User> list = userMapper.findUserList("老郭");
System.out.println(list);
}
@Test
public void testInsertUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);
User user = new User();
user.setUsername("開課吧-2");
user.setSex("1");
user.setAddress("致真大廈");
userMapper.insertUser(user);
System.out.println(user.getId());
}
}
複製程式碼
2. 全域性配置檔案
2.1 配置內容
SqlMapConfig.xml中配置的內容和順序如下:
properties(屬性)
settings(全域性配置引數)
typeAliases(型別別名)
typeHandlers(型別處理器)--Java型別--JDBC型別--->資料庫型別轉換
objectFactory(物件工廠)
plugins(外掛)--可以在Mybatis執行SQL語句的流程中,橫叉一腳去實現一些功能增強,比如PageHelper分頁外掛,就是第三方實現的一個外掛
environments(環境集合屬性物件)
environment(環境子屬性物件)
transactionManager(事務管理)
dataSource(資料來源)
mappers(對映器)
複製程式碼
2.2 properties標籤
SqlMapConfig.xml可以引用java屬性檔案中的配置資訊。
1、在classpath下定義db.properties檔案,
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
複製程式碼
2、在SqlMapConfig.xml檔案中,引用db.properties中的屬性,具體如下:
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
複製程式碼
properties標籤除了可以使用resource屬性,引用properties檔案中的屬性。還可以在properties標籤內定義property子標籤來定義屬性和屬性值,具體如下:
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
</properties>
複製程式碼
注意: MyBatis 將按照下面的順序來載入屬性:
- 讀取properties 元素體內定義的屬性。
- 讀取properties 元素中resource或 url 載入的屬性,它會覆蓋已讀取的同名屬性。
2.3 typeAlias標籤
別名的作用:就是為了簡化對映檔案中parameterType和ResultType中的POJO型別名稱編寫。
2.3.1 預設支援別名
別名 | 對映的型別 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
2.3.2 自定義別名
在SqlMapConfig.xml中進行如下配置:
<typeAliases>
<!-- 單個別名定義 -->
<typeAlias alias="user" type="com.kkb.mybatis.po.User"/>
<!-- 批量別名定義,掃描整個包下的類,別名為類名(首字母大寫或小寫都可以) -->
<package name="com.kkb.mybatis.po"/>
</typeAliases>
複製程式碼
2.4 mappers標籤
<mapper resource=""/>
使用相對於類路徑的資源
如:
<mapper resource="sqlmap/User.xml" />
複製程式碼
<mapper url="">
使用絕對路徑載入資源
如:
<mapper url="file://d:/sqlmap/User.xml" />
複製程式碼
<mapper class=""/>
使用mapper介面類路徑,載入對映檔案。
如:
<mapper class="com.kkb.mybatis.mapper.UserMapper"/>
複製程式碼
注意:此種方法要求mapper介面名稱和mapper對映檔名稱相同,且放在同一個目錄中。
<package name=""/>
註冊指定包下的所有mapper介面,來載入對映檔案。
如:
<package name="com.kkb.mybatis.mapper"/>
複製程式碼
注意:此種方法要求mapper介面名稱和mapper對映檔名稱相同,且放在同一個目錄中。
3. 輸入對映和輸出對映
3.1 parameterType(輸入型別)
parameterType屬性可以對映的輸入引數Java型別有:簡單型別、POJO型別、Map型別、List型別(陣列)。
Map型別和POJO型別的用法類似,這裡只講POJO型別的相關配置。
List型別在動態SQL部分進行講解。
傳遞簡單型別
參考《Mybatis基礎》(在我的主頁內查詢)中使用者查詢的案例。
傳遞pojo物件
參考《Mybatis基礎》(在我的主頁內查詢)中的新增使用者的案例。
傳遞pojo包裝物件
包裝物件:pojo類中巢狀pojo。
需求
通過包裝POJO傳遞引數,完成使用者查詢。
QueryVO
定義包裝物件QueryVO
public class QueryVO {
private User user;
}
複製程式碼
SQL語句
SELECT * FROM user where username like '%小明%'
複製程式碼
Mapper檔案
<!-- 使用包裝型別查詢使用者
使用ognl從物件中取屬性值,如果是包裝物件可以使用.操作符來取內容部的屬性
-->
<select id="findUserList" parameterType="queryVo" resultType="user">
SELECT * FROM user where username like '%${user.username}%'
</select>
複製程式碼
Mapper介面
/**
* 使用者管理mapper
*/
public interface UserMapper {
//綜合查詢使用者列表
public List<User> findUserList(QueryVo queryVo)throws Exception;
}
複製程式碼
測試方法
在UserMapperTest測試類中,新增以下測試程式碼:
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//獲得mapper的代理物件
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//建立QueryVo物件
QueryVo queryVo = new QueryVo();
//建立user物件
User user = new User();
user.setUsername("小明");
queryVo.setUser(user);
//根據queryvo查詢使用者
List<User> list = userMapper.findUserList(queryVo);
System.out.println(list);
sqlSession.close();
}
複製程式碼
3.2 resultType(輸出型別)
resultType屬性可以對映的java型別有:簡單型別、POJO型別、Map型別。
不過Map型別和POJO型別的使用情況類似,所以只需講解POJO型別即可。
3.2.1 使用要求
使用resultType進行輸出對映時,要求sql語句中查詢的列名和要對映的pojo的屬性名一致。
3.2.2 對映簡單型別
案例需求
查詢使用者記錄總數。
Mapper對映檔案
<!-- 獲取使用者列表總數 -->
<select id="findUserCount" resultType="int">
select count(1) from user
</select>
複製程式碼
Mapper介面
//查詢使用者總數
public int findUserCount() throws Exception;
複製程式碼
測試程式碼
在UserMapperTest測試類中,新增以下測試程式碼:
@Test
public void testFindUserCount() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
//獲得mapper的代理物件
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int count = userMapper.findUserCount(queryVo);
System.out.println(count);
sqlSession.close();
}
複製程式碼
注意:輸出簡單型別必須查詢出來的結果集只有一列。
3.2.3 對映pojo物件
注意:不管是單個POJO還是POJO集合,在使用resultType完成對映時,用法一樣。
參考《Mybatis基礎》(在我的主頁內查詢)中根據使用者ID查詢使用者資訊和根據名稱模糊查詢使用者列表的案例
4. resultMap
4.1 使用要求
如果sql查詢列名和pojo的屬性名可以不一致,通過resultMap將列名和屬性名作一個對應關係,最終將查詢結果對映到指定的pojo物件中。
注意:resultType底層也是通過resultMap完成對映的。
4.2 需求
將以下sql的查詢結果進行對映:
SELECT id id_,username username_,birthday birthday_ FROM user
複製程式碼
4.3 Mapper介面
// resultMap入門
public List<User> findUserListResultMap() throws Exception;
複製程式碼
4.4 Mapper對映檔案
由於sql查詢列名和User類屬性名不一致,所以不能使用resultType進行結構對映。
需要定義一個resultMap將sql查詢列名和User類的屬性名對應起來,完成結果對映。
<!-- 定義resultMap:將查詢的列名和對映的pojo的屬性名做一個對應關係 -->
<!--
type:指定查詢結果要對映的pojo的型別
id:指定resultMap的唯一標示
-->
<resultMap type="user" id="userListResultMap">
<!--
id標籤:對映查詢結果的唯一列(主鍵列)
column:查詢sql的列名
property:對映結果的屬性名
-->
<id column="id_" property="id"/>
<!-- result標籤:對映查詢結果的普通列 -->
<result column="username_" property="username"/>
<result column="birthday_" property="birthday"/>
</resultMap>
<!-- resultMap入門 -->
<select id="findUserListResultMap" resultMap="userListResultMap">
SELECT id id_,username username_,birthday birthday_ FROM user
</select>
複製程式碼
<id/>:表示查詢結果集的唯一標識,非常重要。如果是多個欄位為複合唯一約束則定義多個
Property:表示User類的屬性。
Column:表示sql查詢出來的欄位名。
Column和property放在一塊兒表示將sql查詢出來的欄位對映到指定的pojo類屬性上。
<result/>:普通結果,即pojo的屬性。
本系列文章Github 後端進階指南 已收錄,此專案正在完善中,歡迎star。
公眾號內文章都是博主原創,並且會一直更新。如果你想見證或和博主一起成長,歡迎關注!