MyBatis學習筆記
- 介紹篇
-
- 認識架構
- 軟體開發的三層結構
- 認識設計模式
- 回顧JDBC代碼
- 認識Mybatis
- 基礎篇
-
- MyBatis入門
-
- 開發流程
- 需求
- 項目搭建
- 實作需求
-
- 根據id查詢使用者資訊
- 根據使用者名模糊查詢使用者資訊
- 添加使用者
- 删除使用者
- 修改使用者
- 開發dao方式
-
- 原始dao方式
- mapper代理方式(推薦)
-
- 基于 XML 方式
- 基于注解
- 全局配置檔案
-
- properties 标簽
- typeAlias 标簽
- mappers 标簽
- 輸入映射和輸出映射
-
- parameterType(輸入類型)
- resultType(輸出類型)
- resultMap
介紹篇
認識架構
什麼是架構?
- 可以說,一個架構是一個可複用的設計構件,它規定了應用的體系結構,闡明了整個設計、協作構件之間的依賴關系、責任配置設定和控制流程,表現為一組抽象類以及其執行個體協作的方法,它為構件複用提供了上下文(Context)關系。是以構件庫的大規模重用也需要架構。
為什麼使用架構?
- 因為軟體系統發展到今天已經很複雜了,特别是伺服器端軟體,涉及到的知識、内容,問題太多。
- 在某些方面使用别人成熟的架構,就相當于讓别人幫你完成一些基礎工作,你隻需要集中精力完成系統的業務邏輯設計。
- 而且架構一般是成熟、穩健的,它可以處理系統很多細節問題,比如:事務處理、安全性、資料流控制等問題。
- 還有架構一般都經過很多人使用,是以結構很好,擴充性也很好,而且它是不斷更新,你可以直接享用别人更新代碼帶來的好處。
軟體開發的三層結構
- 我們用三層結構主要是使項目結構更清楚,分工更明确,有利于後期的維護和更新。
- 三層結構包含:表現層、業務層、持久層
認識設計模式
設計模式概述
- 設計模式(Design pattern)代表了最佳的實踐,通常被有經驗的面向對象的軟體開發人員所采用。
- 設計模式是軟體開發人員在軟體開發過程中面臨的一般問題的解決方案,這些方案是衆多軟體開發人員經過相當長的一段時間的試驗和錯誤總結出來的。
- 設計模式是一套被反複使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人了解、保證代碼可靠性。
- 設計模式不是一種方法和技術,而是一種思想。
- 設計模式和具體的語言無關,學習設計模式就是要建立面向對象的思想,盡可能的面向接口程式設計,低耦合,高内聚,使設計的程式可複用。
- 學習設計模式能夠促進對面向對象思想的了解,反之亦然。它們相輔相成。
設計模式的類型
總體來說,設計模式分為三類23種:
- 建立型(5種):工廠模式、抽象工廠模式、單例模式、原型模式、建構者模式
- 結構型(7種):擴充卡模式、裝飾模式、代理模式、外觀模式、橋接模式、組合模式、享元模式
- 行為型(11種):模闆方法模式、政策模式、觀察者模式、中介者模式、狀态模式、責任鍊模式、指令模式、疊代器模式、通路者模式、解釋器模式、備忘錄模式
JavaEE設計模式:MVC、委托模式
回顧JDBC代碼
public class JdbcTest {
private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
private static final String DB_URL = "jdbc:mysql://192.168.254.128:3306/ssm?characterEncoding=utf-8";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "123456";
private static final String TEST_SQL = "select * from user where id = ?";
public static void main(String[] args) {
findUserById(1);
}
private static void findUserById(int id) {
try {
// 1、加載驅動
Class.forName(JDBC_DRIVER);
// 2、得到連接配接
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
// 3、擷取預處理statement
PreparedStatement ps = conn.prepareStatement(TEST_SQL)) {
// 4、設定參數
ps.setObject(1, id);
// 5、執行SQL
try (ResultSet rs = ps.executeQuery()) {
// 6、周遊結果集
while (rs.next()) {
String result = String.format("{id = %d, username = %s, sex = %s}",
rs.getInt("id"),
rs.getString("username"),
rs.getString("sex"));
System.out.println(result);
}
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
認識Mybatis
- mybatis參考網址:http://www.mybatis.org/mybatis-3/zh/index.html
- github源碼位址:https://github.com/mybatis/mybatis-3
什麼是Mybatis?
- 持久層架構
- 封裝了JDBC代碼,但是完全屏蔽了JDBC代碼的相關操作
- 用XML或者注解方式,去使用mybatis架構完成持久化操作
- mybatis會使用進階映射來完成參數處理和傳回值映射
- mybatis是直接操作原生的SQL語句
Mybatis的由來
- 是apache的一個開源項目iBatis
- 2010年這個項目由apache software foundation遷移到google code,并改名為Mybatis
- 2013年11月遷移到Github
ORM架構
- Object Relation Mapping,例如:Hibernate
mybatis和ORM架構hibernate的差別
- mybatis是一個不完全的ORM架構,而hibernate是一個完全的ORM架構
- mybatis學習成本低,hibernate學習成本高
- mybatis資料庫無關性不好,hibernate資料庫無關性好
- mybatis是直接操作SQL語句,它更加靈活,而hibernate是操作的HQL語句
基礎篇
MyBatis入門
開發流程
- 編寫全局配置檔案:SqlMapConfig.xml
- properties标簽:讀取Java配置檔案(properties檔案)
- typeAliases标簽:對PO類的全路徑(全限定名)做别名處理,友善xml配置
- mappers标簽:加載映射檔案
- 編寫PO類
- 隻有私有屬性和getter、setter方法的javabean
- 隻是在不同場景下,有了不同的定義
- 編寫映射檔案
- 編寫原生SQL語句(符合SQL92标準和MySQL标簽的語句)
- 資料參數映射
- 結果集映射
- 編寫持久層代碼
- 如何讀取全局配置檔案、還有映射檔案
- SqlSessionFactoryBuilder(全局配置檔案對應的流對象)
- SqlSessionFactory(擷取SqlSession)
- SqlSession
- 如何調用映射檔案中的SQL語句,完成對資料庫的增删改查
- 調用SqlSession中的api完成增删改查功能
- 如何讀取全局配置檔案、還有映射檔案
需求
- 根據使用者id查詢一個使用者資訊
- 根據使用者名稱模糊查詢使用者資訊清單
- 添加使用者
- 更新使用者
- 删除使用者
項目搭建
- 建立一個普通的 maven工程,添加依賴:
<!-- mysql依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- mybatis依賴 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- junit單元測試依賴 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- lombok依賴 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
- 編寫 SqlMapConfig.xml 全局檔案
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 讀取properties配置檔案 -->
<properties resource="properties/db.properties"></properties>
<!-- 配置資料源 -->
<environments default="development">
<environment id="development">
<!-- 事務管理:采用的是JDBC的事務管理 -->
<transactionManager type="JDBC"/>
<!-- 配置資料源連接配接池:POOLED使用的是Mybatis自己的連接配接池 -->
<dataSource type="POOLED">
<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>
<!-- 讀取mapper映射檔案 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
- 編寫 UserMapper.xml 映射檔案
<?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">
<!-- namespace:作用是為了分類管理映射檔案中的MappedStatement對象 -->
<mapper namespace="test">
<!--
select\insert\update\delete标簽,最終會封裝到MappedStatement對象中
id:指定MappedStatement對象的唯一辨別
對象參數綁定:使用OGNL
parameterType:指定輸入參數映射的java類型
resultType:指定結果集映射的java類型
-->
<select id="findUserById" parameterType="int" resultType="com.yw.mybatis.example.po.User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
- 編寫 User.java PO類
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
}
實作需求
根據id查詢使用者資訊
- 映射檔案
<!-- 根據id擷取使用者資訊 -->
<select id="findUserById" parameterType="int" resultType="com.yw.mybatis.example.po.User">
SELECT * FROM user WHERE id = #{id}
</select>
- 測試代碼
public class MybatisDemo {
// sql會話工廠,抽取代碼,友善重用
private SqlSessionFactory sqlSessionFactory;
/**
* @Before注解的方法會在@Test注解的方法之前執行
* @throws Exception
*/
@Before
public void init() throws Exception{
// 指定全局配置檔案路徑
String resource = "SqlMapConfig.xml";
// 加載資源檔案(全局配置檔案和映射檔案)
// 最終全局配置檔案的資料,都會封裝到一個對象中:Configuration對象
InputStream inputStream = Resources.getResourceAsStream(resource);
// 用建構者模式,去建立SqlSessionFactory對象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception{
SqlSession sqlSession = null;
try {
// 構造UserMapper對象(sqlSession),該步操作會牽扯到事務
// 設定手動送出才能開啟事務,預設是手動送出
sqlSession = sqlSessionFactory.openSession();
/*
參數1:和映射檔案中的select标簽建立聯系:namespace+"."+statementID
參數2:就是要傳遞的參數
*/
User user = sqlSession.selectOne("test.findUserById", 1);
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(sqlSession != null){
sqlSession.close();
}
}
}
}
根據使用者名模糊查詢使用者資訊
- 映射檔案
<!-- 自定義條件查詢使用者清單 -->
<select id="findUserByUsername" parameterType="java.lang.String"
resultType="com.yw.mybatis.example.po.User">
select * from user where username like '%${value}%'
</select>
- 測試代碼
@Test
public void testFindUserByUsername() throws Exception{
SqlSession sqlSession = null;
try {
// 構造UserMapper對象(sqlSession),該步操作會牽扯到事務
// 設定手動送出才能開啟事務,預設是手動送出
sqlSession = sqlSessionFactory.openSession();
/*
參數1:和映射檔案中的select标簽建立聯系:namespace+"."+statementID
參數2:就是要傳遞的參數
*/
List<User> users = sqlSession.selectList("test.findUserByUsername", "張");
System.out.println(users.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
if(sqlSession != null){
sqlSession.close();
}
}
}
#{} 和${}的差別
- 差別1:#{} 相當于JDBC SQL語句中的占位符 ? (PreparedStatement);${} 相當于JDBC SQL語句中的連接配接符号+(Statement)
- 差別2:#{} 進行輸入映射的時候,會對參數進行類型解析(如果是String類型,會自動加上’’);${} 進行輸入映射的時候,将參數原樣輸出到SQL語句中。
- 差別3:#{} 如果進行簡單類型(8大基本資料類型)的輸入映射,#{}中參數名稱可以任意;${} 如果進行簡單類型(8大基本資料類型)的輸入映射,${}中參數名稱必須是value。
- 差別4:${} 存在SQL注入問題,例如使用OR 1=1 關鍵字将查詢條件忽略。
添加使用者
- 映射檔案
<!-- 添加使用者 -->
<insert id="insertUser" parameterType="com.yw.mybatis.example.po.User">
insert into user(username, birthday, sex, address)
values(#{username}, #{birthday}, #{sex}, #{address})
</insert>
- 測試代碼
@Test
public void testInsertUser() throws Exception{
SqlSession sqlSession = null;
try {
// 建立資料庫會話執行個體sqlSession
sqlSession = sqlSessionFactory.openSession();
// 添加使用者資訊
User user = new User();
user.setUsername("Alice");
user.setAddress("US");
user.setSex("女");
user.setBirthday(new Date());
sqlSession.insert("test.insertUser", user);
// 送出事務
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(sqlSession != null){
sqlSession.close();
}
}
}
- 主鍵傳回
<!-- 添加使用者 -->
<insert id="insertUser" parameterType="com.yw.mybatis.example.po.User">
<!-- selectKey将主鍵傳回,需要再傳回 -->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username, birthday, sex, address)
values(#{username}, #{birthday}, #{sex}, #{address})
</insert>
- 添加selectKey标簽實作主鍵傳回
- keyProperty:指定傳回的主鍵,存儲在pojo中的那個屬性。
- order:selectKey标簽中的sql的執行順序,是相對于insert語句來說的。由于mysql的自增原理,執行完insert語句之後才将主鍵生成,是以這裡selectKey的執行順序為after。
- resultType:傳回的主鍵對應的Java類型。
- LAST_INSERT_ID():是mysql的函數,傳回auto_increment自增列新紀錄id值。
删除使用者
- 映射檔案
<!-- 删除使用者 -->
<delete id="deleteUserById" parameterType="int">
delete from user where id = #{id}
</delete>
- 測試代碼
@Test
public void testDeleteUserById() throws Exception{
SqlSession sqlSession = null;
try {
// 建立資料庫會話執行個體sqlSession
sqlSession = sqlSessionFactory.openSession();
// 删除使用者
sqlSession.delete("test.deleteUserById", 4);
// 送出事務
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(sqlSession != null){
sqlSession.close();
}
}
}
修改使用者
- 映射檔案
<!-- 更新使用者 -->
<update id="updateUser" parameterType="com.yw.mybatis.example.po.User">
update user set
username = #{username},
birthday = #{birthday},
sex = #{sex},
address = #{address}
where id = #{id}
</update>
- 測試代碼
@Test
public void testUpdateUser() throws Exception{
SqlSession sqlSession = null;
try {
// 建立資料庫會話執行個體sqlSession
sqlSession = sqlSessionFactory.openSession();
// 修改使用者資訊
User user = new User();
user.setId(3);
user.setUsername("Alice");
user.setAddress("BALABALA");
user.setSex("男");
user.setBirthday(new Date());
sqlSession.insert("test.updateUser", user);
// 送出事務
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(sqlSession != null){
sqlSession.close();
}
}
}
開發dao方式
原始dao方式
說明:該種方式一般來說隻會出現在那些從 ibatis 項目遷移過來的項目
- SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession的生命周期
- SqlSessionFactoryBuilder:method方法内的局部變量。
- SqlSessionFactory:應用範圍内唯一。
- SqlSession:method方法範圍。牽涉到線程安全問題,原因在于sqlsession實作類對象中會包含全局資料(參數和傳回值)
- dao 接口和實作類
public interface UserDao {
User findUserById(int id) throws Exception;
}
public class UserDaoImpl implements UserDao {
// 依賴注入
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id){
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = null;
try{
user = sqlSession.selectOne("dao.test.findUserById", 1);
}finally{
sqlSession.close();
}
return user;
}
}
- 映射檔案
<mapper namespace="dao.test">
<!-- 根據id擷取使用者資訊 -->
<select id="findUserById" parameterType="int" resultType="com.yw.mybatis.example.po.User">
select * from user where id = #{id}
</select>
</mapper>
- 測試代碼
public class UserDaoTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init(){
try {
// 指定全局配置檔案路徑
String resource = "dao/SqlMapConfig.xml";
// 加載資源檔案(全局配置檔案和映射檔案)
InputStream inputStream = Resources.getResourceAsStream(resource);
// 用建構者模式,去建立SqlSessionFactory對象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testFindUserById(){
UserDao dao = new UserDaoImpl(sqlSessionFactory);
User user = dao.findUserById(1);
System.out.println(user);
}
}
mapper代理方式(推薦)
- 使用mapper代理方式開發dao,是隻需要定義dao接口(mapper接口),不需要dao實作類。Mybatis底層使用的是動态代理方式幫助我們産生dao實作類:
- 基于JDK的動态代理(Mybatis的mapper代理方式,是基于JDK的動态代理):基于接口。
- 基于CGLib的動态代理:基于繼承。
- 使用mapper代理方法開發dao,除了PO類和全局配置檔案以外,隻需要編寫映射檔案和Mapper接口(dao接口)
基于 XML 方式
- 使用:隻需要開發Mapper接口(dao接口)和Mapper限制檔案,不需要編寫實作類
- 開發規範:
- 映射檔案的namespace和mapper接口的類路徑要一緻;
- 映射檔案的statement的id和和mapper接口的方法名要一緻;
- 映射檔案的statement的parameterType和mapper接口的方法參數類型要一緻;
- 映射檔案的statement的resultType和mappper接口的方法傳回值類型要一緻
- 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.yw.mybatis.example.mapper.xml.UserMapper">
<!-- 根據id擷取使用者資訊 -->
<select id="findUserById" parameterType="int" resultType="com.yw.mybatis.example.po.User">
select * from user where id = #{id}
</select>
</mapper>
- mapper接口
public interface UserMapper {
User findUserById(int id);
}
- 加載映射檔案
<mappers>
<!-- 批量加載 -->
<package name="com.yw.mybatis.example.mapper.xml"/>
</mappers>
- 測試代碼
public class XmlUserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init(){
try {
// 指定全局配置檔案路徑
String resource = "XmlSqlMapConfig.xml";
// 加載資源檔案(全局配置檔案和映射檔案)
InputStream inputStream = Resources.getResourceAsStream(resource);
// 用建構者模式,去建立SqlSessionFactory對象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testFindUserById() throws Exception {
// 構造UserMapper對象(sqlSession)
SqlSession sqlSession = sqlSessionFactory.openSession();
// 需要傳的參數就是被代理的Mapper接口
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 調用UserMapper對象的findUserById
User user = userMapper.findUserById(1);
System.out.println(user);
}
}
基于注解
- 定義 mapper 接口
public interface AnnotationUserMapper {
@Select("select * from user where id = #{id}")
User findUserById(int id);
}
- 修改全局配置檔案
<mappers>
<!-- 批量加載 -->
<package name="com.yw.mybatis.example.mapper.annotation"/>
</mappers>
- 測試代碼
public class AnnotationUserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init(){
try {
// 指定全局配置檔案路徑
String resource = "AnnotationSqlMapConfig.xml";
// 加載資源檔案(全局配置檔案和映射檔案)
InputStream inputStream = Resources.getResourceAsStream(resource);
// 用建構者模式,去建立SqlSessionFactory對象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testFindUserById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
}
}
全局配置檔案
- 配置内容:SqlMapConfig.xml 中配置的内容和順序如下
- properties:屬性
- settings:全局配置參數
- typeAliases:類型别名
- typeHandlers:類型處理器——Java類型——JDBC類型——>資料庫類型轉換
- objectFactory:對象工廠
- plugins:插件——可以在Mybatis執行SQL語句的流程中,橫叉一腳去實作一些功能增強,比如PageHelper分頁插件
- environments:環境集合屬性對象
- environment:環境子屬性對象
- transactionManager:事務管理
- dataSource:資料源
- environment:環境子屬性對象
- mappers:映射器
- mapper:映射
properties 标簽
- 可以引用java屬性檔案中的配置資訊,例如在 classpath 下定義的db.properties檔案
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
db.username=root
db.password=root
- 要在 SqlMapConfig.xml 中引用db.properties中的屬性時,如下:
<!-- 讀取properties配置檔案 -->
<properties resource="properties/db.properties"></properties>
<!-- 配置資料源 -->
<environments default="development">
<environment id="development">
<!-- 事務管理:采用的是JDBC的事務管理 -->
<transactionManager type="JDBC"/>
<!-- 配置資料源連接配接池:POOLED使用的是Mybatis自己的連接配接池 -->
<dataSource type="POOLED">
<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>
- properties标簽除了可以使用resource屬性引用properties檔案中的屬性,還可以在properties标簽内定義property子标簽來定義屬性和屬性值
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"></property>
</properties>
- 注意:Mybatis将按照下面的順序來加載屬性
1)讀取properties元素内定義的屬性
2)讀取properties元素中resource或url加載的屬性,它會覆寫已讀取的同名屬性
typeAlias 标簽
- 别名的作用是簡化映射檔案中parameterType和resultType中的POJO類型名稱編寫,下面是預設支援的别名
别名 | 映射類型 |
---|---|
_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 |
- 自定義别名:在SqlMapConfig.xml中進行如下配置
<typeAliases>
<!-- 單個别名定義 -->
<typeAlias alias="user" type="com.yw.mybatis.example.po.User"/>
<!-- 批量别名定義,掃描整個包下的類,别名為類名(首字母大小寫都可以) -->
<package name="com.yw.mybatis.example.po"/>
</typeAliases>
mappers 标簽
- <mapper resource=""/>:使用相對于類路徑的資源
- <mapper url=""/>:使用絕對路徑加載資源
- <mapper class=""/>:使用mapper接口類路徑,加載映射檔案。注意:此種方法要求mapper接口名稱和mapper映射檔案名稱相同,且放在同一個目錄中
- <package name=""/>:注冊指定包下的所有mapper接口,來加載映射檔案。注意:此種方法要求mapper接口名稱和mapper映射檔案名稱相同,且放在同一個目錄中
輸入映射和輸出映射
parameterType(輸入類型)
- parameterType屬性可以映射的輸入類型有:簡單類型、POJO類型、Map類型、List類型(數組),其中 Map類型和POJO類型用法類似
- 應用場景:傳遞簡單類型、傳遞pojo對象、傳遞pojo包裝對象
- 包裝對象:pojo類中包含pojo
- #{}:是通過反射擷取資料的——StaticSqlSource
- ${}:是通過OGNL表達式會随着對象的嵌套而相應的發生層級變化——DynamicSqlSource
- 包裝對象:pojo類中包含pojo
resultType(輸出類型)
- resultType 屬性可以映射的java類型有:簡單類型、POJO類型、Map類型,不過Map類型和POJO類型的使用情況類似。
- 使用要求:使用resultType進行輸出映射時,要求sql語句中查詢的列名要和映射的pojo屬性名一緻
- 應用場景:映射簡單類型、映射pojo對象
- 注意:不管是單個的POJO還是POJO集合,在使用resultType完成映射時,用法一樣
resultMap
- 使用要求:如果sql查詢列名和pojo的屬性名不一緻,可以通過resultMap将列名和屬性名做一個對應關系,最終将查詢結果映射到指定的pojo對象中。
- 注意:resultType底層也是通過resultMap完成映射的
- 需求:将以下查詢結果進行映射:
- Mapper 映射檔案:由于sql查詢列名和User類屬性名不一緻,是以不能使用resultType進行結構映射,需要定義一個resultMap将sql查詢列名和User類的屬性名對應起來,完成結果映射
<!--
定義resultMap:将查詢的列名和pojo的屬性名一一對應起來
type:指定查詢結果要映射的pojo的類型
id:指定resultMap的唯一辨別
-->
<resultMap type="user" id="userListResultMap">
<!--
id标簽:映射結果的唯一列(主鍵列)
column:查詢sql的列名
property:映射結果的屬性名
result:普通結果,即pojo的屬性
-->
<id column="id_" property="id"/>
<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>