Mybatis組態檔&SQL映射檔案
1.組態檔-mybatis-config.xml
1.1基本說明
mybatis的核心組態檔(mybatis-config.xml),它的作用如配置jdbc連接資訊,注冊mapper等,我們需要對這個組態檔有詳細的了解,
檔案地址:mybatis – MyBatis 3 | 配置
配置檔案的頂層結構如下:
1.2properties(屬性)
屬性可以在外部進行配置,并可以進行動態替換(使用${}),既可以在典型的 Java 屬性檔案中配置這些屬性,也可以在 properties 元素的子元素中設定,
(1)直接在properties元素的子元素中配置
<dataSource type="POOLED">
<property name="driver" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/com.mysql.jdbc.Driver"/>
<property name="url" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/jdbc:mysql://127.0.0.1:3306/mybatis?
useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/root"/>
<property name="password" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/123456"/>
</dataSource>
(2)在外部配置,進行動態替換
jdbc.properties 屬性檔案:
.properties 屬性檔案需要統一放在 resource 目錄/類加載路徑
# The key value is arbitrary
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
jdbc.user=root
jdbc.pwd=123456
mybatis 組態檔:
要先引入 .properties 檔案
<configuration>
<!--引入外部的jdbc.properties-->
<properties resource="jdbc.properties"/>
<dataSource type="POOLED">
<property name="driver" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${jdbc.driver}"/>
<property name="url" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${jdbc.url}"/>
<property name="username" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${jdbc.user}"/>
<property name="password" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${jdbc.pwd}"/>
</dataSource>
</configuration>
1.3settings(設定)
mybatis – MyBatis 3 | 配置
1.4typeAliases(別名處理器)
- 別名是Java命名一個短名稱,它只和XML配置有關,用來減少類名重復的部分
- 如果指定了別名,我們的xxMapper.xml檔案就可以做相應的簡化處理
- 注意指定別名后,還是可以使用全名的
- 如果一個包下有很多的類,我們可以直接引入包,這樣該包下面的所有類名都可以直接使用,
<typeAliases>
<!--如果一個包下有很多的類,可以直接使用包的方式引入,這樣包下的所有類名都可以直接使用-->
<package name="com.li.entity"/>
</typeAliases>
1.5typeHandlers(型別處理器)
- 用于Java型別和jdbc型別映射
- Mybatis的映射基本已經滿足,不太需要重新定義
- 這個我們默認即可,也就是mybatis會自動地將java和jdbc型別進行轉換
- Java型別和jdbc型別映射關系一覽 mybatis – MyBatis 3 | 配置
1.6environments(環境)
environments 元素定義了如何配置環境,
注意一些關鍵點:
- 默認使用的環境 ID(比如:default="development"),
- 每個 environment 元素定義的環境 ID(比如:id="development"),
- 事務管理器的配置(比如:type="JDBC"),
- 資料源的配置(比如:type="POOLED"),
默認環境和環境 ID 顧名思義, 環境可以隨意命名,但務必保證默認的環境 ID 要匹配其中一個環境 ID,
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${driver}"/>
<property name="url" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${url}"/>
<property name="username" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${username}"/>
<property name="password" value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/${password}"/>
</dataSource>
</environment>
</environments>
1.7mappers(映射器)
現在就要來定義 SQL 映射陳述句了, 首先,我們需要告訴 MyBatis 到哪里去找到這些陳述句,你可以使用相對于類路徑的資源參考,或完全限定資源定位符(包括 file:/// 形式的 URL),或類名和包名等,
(1)使用相對于類路基的資源參考
<!-- 使用相對于類路徑的資源參考 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
(2)使用完全限定資源定位符(URL),不推薦使用
<!-- 使用完全限定資源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
(3)使用映射器介面實作類的完全限定類名
<!-- 使用映射器介面實作類的完全限定類名 -->
<mappers>
<mapper />
<mapper />
<mapper />
</mappers>
(4)將包內的映射器介面全部注冊為映射器
<!-- 將包內的映射器介面全部注冊為映射器
1.當一個包下有很多的xxMapper.xml檔案和基于注解實作的介面時,為了方便,可以用包方式進行參考
2.將下面的所有xml檔案和注解介面都進行注冊-->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
2.SQL映射檔案-xxMapper.xml
2.1基本介紹
mybatis – MyBatis 3 | XML 映射器
-
Mybatis 的真正強大之處在于它的陳述句映射(在XxxMapper.xml中配置),如果拿它和具有相同功能的 JDBC代碼進行對比,你會發現立即省掉了將近 95% 的代碼,MyBatis 致力于減少使用成本,讓用戶能更專注于SQL 代碼,
-
SQL映射檔案常用的頂級元素(按照應被定義的順序列出):
-
cache - 該命名空間的快取配置
-
cache-ref - 參考其他命名空間的快取配置
-
resultMap - 描述如何從資料庫的結果集 中加載物件,是最復雜也是最強大的元素
-
parameterType - 將會傳入這條陳述句的引數的類全限定名或別名
-
sql - 可被其他陳述句參考的可重用陳述句塊
-
insert - 映射插入陳述句
-
update - 映射更新陳述句
-
delete - 映射洗掉陳述句
-
select - 映射查詢陳述句
-
2.2映射檔案詳細說明
2.2.1基本使用
-
insert,delete,update,select 這些在之前講過,分別對應增刪查改的方法和SQL陳述句的映射
-
如果獲取到剛剛添加的Monster物件的id主鍵(獲取自增長)也講過了
<insert id="addMonster" parameterType="Monster" useGeneratedKeys="true" keyProperty="id"> INSERT INTO `monster` (`age`,`birthday`,`email`,`gender`,`name`,`salary`) VALUES (#{age},#{birthday},#{email},#{gender},#{name},#{salary}) </insert>
2.2.2傳入型別-POJO或String
- 當有多個條件時,傳入的引數設為POJO/Entity型別的 Java物件,這樣可以通過 POJO/Entity 物件的屬性來接收傳入的引數
- 傳入 POJO/Entity 型別時,如果查詢時需要有多個篩選條件,怎么在映射檔案中處理?一般是使用
#{}的方式來獲取入參的多個值(注意#{}內部的名稱對應的是POJO物件的屬性名,和表欄位無關) - 當傳入的引數型別為String時,則使用
${}的方式來接收傳入的引數
應用案例
(1)MonsterMapper.java 介面
package com.li.mapper;
import com.li.entity.Monster;
import java.util.List;
/**
* @author 李
* @version 1.0
*/
public interface MonsterMapper {
//通過id或者名字查詢
public List<Monster> findMonsterByNameOrId(Monster monster);
//查詢名字中含有‘精’的妖怪
public List<Monster> findMonsterByName(String name);
}
(2)映射檔案MonsterMapper.xml 實作介面方法
<mapper namespace="com.li.mapper.MonsterMapper">
<!--這里 #{}的值是從傳入的引數的屬性中獲取的,`id`表示表的欄位名,
這里的parameterType可以直接使用類名,是因為在mybatis的組態檔中配置了別名-->
<select id="findMonsterByNameOrId" parameterType="Monster" resultType="Monster">
SELECT * FROM `monster` WHERE `id` = #{id} OR `name` = #{name}
</select>
<!--當傳入的引數型別為String時,使用${}的方式來接收引數-->
<select id="findMonsterByName" parameterType="String" resultType="Monster">
SELECT * FROM `monster` WHERE `name` LIKE '%${name}%'
</select>
</mapper>
(3)測驗
package com.li.mapper;
import com.li.entity.Monster;
import com.li.util.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
/**
* @author 李
* @version 1.0
*/
public class MonsterMapperTest {
//屬性
private SqlSession sqlSession;
private MonsterMapper monsterMapper;
//初始化
@Before
public void init() {
sqlSession = MybatisUtils.getSqlSession();
monsterMapper = sqlSession.getMapper(MonsterMapper.class);
System.out.println("monsterMapper=" + monsterMapper.getClass());
}
@Test
public void findMonsterByNameOrId() {
Monster monster = new Monster();
monster.setId(1);
monster.setName("狐貍精");
List<Monster> monsters =
monsterMapper.findMonsterByNameOrId(monster);
for (Monster m : monsters) {
System.out.println("m=" + m);
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("findMonsterByNameOrId() 查詢成功!");
}
@Test
public void findMonsterByName() {
List<Monster> monsters = monsterMapper.findMonsterByName("精");
for (Monster monster : monsters) {
System.out.println("monster=" + monster);
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("findMonsterByName() 查詢成功!");
}
}
2.2.3傳入型別-Map
HashMap傳入引數更加靈活,比如可以靈活地增加查詢的屬性,而不受POJO/Entity 型別本身屬性的限制(因為POJO/Entity 型別的屬性數量有限而且#{}中的名稱必須為屬性名)
例子-演示如何遍歷一個List<Map<String,Object>> 的資料型別
(1)修改MonsterMapper.java,增加方法介面
//宣告一個方法,傳入引數是HashMap,查詢 id>10 并且 salary>40 的所有妖怪
public List<Monster> findMonsterByIdAndSalary(Map<String, Object> map);
(2)修改MonsterMapper.xml映射檔案,實作該方法
<!--宣告一個方法,傳入引數是HashMap,查詢 id>5 并且 salary>40 的所有妖怪
這里使用 #{id}和 #{salary} 來獲取入參 map的值時,意味著你的map需要有key為id和salary的鍵值對
事實上,map的 key 只要和 #{}中的 key一樣即可,和表欄位無關-->
<select id="findMonsterByIdAndSalary" parameterType="map" resultType="Monster">
SELECT * FROM `monster` WHERE `id`>#{id} AND `salary` > #{salary}
</select>
(3)測驗
@Test
public void findMonsterByIdAndSalary() {
Map<String, Object> map = new HashMap<>();
map.put("id", 5);//這里設定的key只要和#{key}的key值一樣即可,和表欄位無關
map.put("salary", 40);
List<Monster> monsters = monsterMapper.findMonsterByIdAndSalary(map);
for (Monster monster : monsters) {
System.out.println("monster=" + monster);
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("findMonsterByIdAndSalary() 查詢成功!");
}
2.2.4傳入&回傳的型別都是Map
(1)修改MonsterMapper.java,增加方法介面
//傳入和回傳的型別都是Map
public List<Map<String, Object>> findMonsterByIdAndSalary2(Map<String, Object> map);
(2)修改MonsterMapper.xml映射檔案,實作該方法
<!--查詢 id>5 并且 salary>40 的所有妖怪,要求傳入和回傳的引數都是Map型別-->
<select id="findMonsterByIdAndSalary2" parameterType="map" resultType="map">
SELECT * FROM `monster` WHERE `id`>#{id} AND `salary` > #{salary}
</select>
(3)測驗
@Test
public void findMonsterByIdAndSalary2() {
Map<String, Object> map = new HashMap<>();
map.put("id", 5);
map.put("salary", 40);
List<Map<String, Object>> monstersList = monsterMapper.findMonsterByIdAndSalary2(map);
//取出回傳的結果-以map的形式
for (Map<String, Object> monsterMap : monstersList) {
System.out.println("monsterMap=" + monsterMap);
//遍歷monsterMap,取出屬性和對應的值
for (Map.Entry<String, Object> entry : monsterMap.entrySet()) {
System.out.println("key=" + entry.getKey() + "=>value="https://www.cnblogs.com/liyuelian/archive/2023/02/26/+ entry.getValue());
}
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("findMonsterByIdAndSalary2() 查詢成功!");
}
2.2.5resultMap結果集映射
當物體類屬性和表的欄位名字不一樣時,我們可以通過resultMap進行映射,從而屏蔽物體類屬性名和表的欄位不一致可能出現的問題,
例子
(1)表user
-- 創建user表
CREATE TABLE `user`(
`user_id` INT NOT NULL AUTO_INCREMENT,
`user_email` VARCHAR(255) DEFAULT '',
`user_name` VARCHAR(255) DEFAULT '',
PRIMARY KEY(`user_id`)
)CHARSET=utf8
(2)創建物體類和表映射,這里故意設定和表欄位不一樣的屬性名
package com.li.entity;
/**
* @author 李
* @version 1.0
*/
public class User {
private Integer userId;
private String userName;
private String userEmail;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userEmail='" + userEmail + '\'' +
'}';
}
}
(3)創建介面 UserMapper.java
package com.li.mapper;
import com.li.entity.User;
import java.util.List;
/**
* @author 李
* @version 1.0
*/
public interface UserMapper {
//添加
public void addUser(User user);
//查詢所有的User
public List<User> findAllUsers();
}
(4)創建映射檔案 UserMapper.xm
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace指定該xml檔案和哪個介面對應-->
<mapper namespace="com.li.mapper.UserMapper">
<!--完成添加用戶的任務,注意這里的user屬性和表的字段名不一致
這里的parameterType可以直接使用類名,是因為在mybatis的組態檔中配置了別名-->
<insert id="addUser" parameterType="User">
INSERT INTO `user`(`user_email`,`user_name`)
VALUE(#{userEmail},#{userName});
</insert>
<!--因為表欄位的名稱和物體型別的名稱不一致
1.如果物件屬性名和表欄位不一樣是,那么回傳的資料就保存不進去,就會是物件的屬性就是默認值
2.要解決這個問題,可以使用resultMap來解決這個問題
3.定義一個resultMap,它的id由你指定id,通過id可以參考這個resultMap
4.type 為回傳的資料型別(可以使用別名)
5.column為表的欄位,property為物件的屬性名-->
<resultMap id="findAllUserMap" type="User">
<!--指定映射關系-->
<result column="user_email" property="userEmail"/>
<result column="user_name" property="userName"/>
</resultMap>
<select id="findAllUsers" resultMap="findAllUserMap">
SELECT * FROM `user`
</select>
</mapper>
(5)測驗
package com.li.mapper;
import com.li.entity.User;
import com.li.util.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
/**
* @author 李
* @version 1.0
*/
public class UserMapperTest {
//屬性
private SqlSession sqlSession;
private UserMapper userMapper;
//初始化
@Before
public void init() {
sqlSession = MybatisUtils.getSqlSession();
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void addUser(){
User user = new User();
user.setUserName("marry");
user.setUserEmail("[email protected]");
userMapper.addUser(user);
if (sqlSession != null) {
//需要手動提交事務,因為mybatis事務默認為false
sqlSession.commit();
sqlSession.close();
}
System.out.println("插入成功!");
}
@Test
public void findAllUsers(){
List<User> allUsers = userMapper.findAllUsers();
for (User user : allUsers) {
System.out.println("user="+user);
}
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("查詢成功!");
}
}
resultMap注意事項和細節
-
除了使用resultMap,也可以使用欄位別名解決表欄位和物件屬性不一致的問題,但是它的復用性不好,因此不推薦使用欄位別名
-
如果是MyBatis-Plus處理就比較簡單,可以使用@TableField來解決物體欄位名和表欄位名不一致的問題,還可以使用@TableName來解決物體類名和表名不一致的問題,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/545115.html
標籤:其他
上一篇:面向物件進階第三天
下一篇:并發專題一
