Mybatis-9.28
環(huán)境:
- JDK1.8
- Mysql 5.7
- maven 3.6.1
- IDEA
回顧:
- JDBC
- Mysql
- Java基礎(chǔ)
- Maven
- Junit
SSM框架:配置文件的蝎抽。 最好的方式:看官網(wǎng)文檔;
1羞酗、簡(jiǎn)介
1.1、什么是Mybatis
- MyBatis 是一款優(yōu)秀的持久層框架
- 它支持定制化 SQL无蜂、存儲(chǔ)過程以及高級(jí)映射伺糠。
- MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。
- MyBatis 可以使用簡(jiǎn)單的 XML 或注解來配置和映射原生類型酱讶、接口和 Java 的 POJO(Plain Old Java Objects退盯,普通老式 Java 對(duì)象)為數(shù)據(jù)庫(kù)中的記錄彼乌。
- MyBatis 本是apache的一個(gè)開源項(xiàng)目iBatis, 2010年這個(gè)項(xiàng)目由apache software foundation 遷移到了google code泻肯,并且改名為MyBatis 。
- 2013年11月遷移到Github慰照。
如何獲得Mybatis灶挟?
-
maven倉(cāng)庫(kù):
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency>
1.2、持久化
數(shù)據(jù)持久化
- 持久化就是將程序的數(shù)據(jù)在持久狀態(tài)和瞬時(shí)狀態(tài)轉(zhuǎn)化的過程
- 內(nèi)存:斷電即失
- 數(shù)據(jù)庫(kù)(Jdbc)毒租,io文件持久化稚铣。
- 生活:冷藏. 罐頭。
為什么需要持久化墅垮?
有一些對(duì)象惕医,不能讓他丟掉。
內(nèi)存太貴了
1.3算色、持久層
Dao層抬伺,Service層,Controller層….
- 完成持久化工作的代碼塊
- 層界限十分明顯灾梦。
1.4 為什么需要Mybatis峡钓?
- 幫助程序猿將數(shù)據(jù)存入到數(shù)據(jù)庫(kù)中。
- 方便
- 傳統(tǒng)的JDBC代碼太復(fù)雜了若河。簡(jiǎn)化能岩。框架萧福。自動(dòng)化拉鹃。
- 不用Mybatis也可以。更容易上手鲫忍。 技術(shù)沒有高低之分
- 優(yōu)點(diǎn):
- 簡(jiǎn)單易學(xué)
- 靈活
- sql和代碼的分離毛俏,提高了可維護(hù)性。
- 提供映射標(biāo)簽饲窿,支持對(duì)象與數(shù)據(jù)庫(kù)的orm字段關(guān)系映射
- 提供對(duì)象關(guān)系映射標(biāo)簽煌寇,支持對(duì)象關(guān)系組建維護(hù)
- 提供xml標(biāo)簽,支持編寫動(dòng)態(tài)sql逾雄。
最重要的一點(diǎn):使用的人多阀溶!
Spring SpringMVC SpringBoot
2腻脏、第一個(gè)Mybatis程序
思路:搭建環(huán)境-->導(dǎo)入Mybatis-->編寫代碼-->測(cè)試!
2.1银锻、搭建環(huán)境
搭建數(shù)據(jù)庫(kù)
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'狂神','123456'),
(2,'張三','123456'),
(3,'李四','123890')
新建項(xiàng)目
新建一個(gè)普通的maven項(xiàng)目
刪除src目錄
-
導(dǎo)入maven依賴
<!--導(dǎo)入依賴--> <dependencies> <!--mysql驅(qū)動(dòng)--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--mybatis--> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
2.2永品、創(chuàng)建一個(gè)模塊
-
編寫mybatis的核心配置文件
<?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核心配置文件--> <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://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> </configuration>
-
編寫mybatis工具類
//sqlSessionFactory --> sqlSession public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static{ try { //使用Mybatis第一步:獲取sqlSessionFactory對(duì)象 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //既然有了 SqlSessionFactory,顧名思義击纬,我們就可以從中獲得 SqlSession 的實(shí)例了鼎姐。 // SqlSession 完全包含了面向數(shù)據(jù)庫(kù)執(zhí)行 SQL 命令所需的所有方法。 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
2.3更振、編寫代碼
-
實(shí)體類
package com.kuang.pojo; //實(shí)體類 public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
-
Dao接口
public interface UserDao { List<User> getUserList(); }
-
接口實(shí)現(xiàn)類由原來的UserDaoImpl轉(zhuǎn)變?yōu)橐粋€(gè) 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"> <!--namespace=綁定一個(gè)對(duì)應(yīng)的Dao/Mapper接口--> <mapper namespace="com.kuang.dao.UserDao"> <!--select查詢語句--> <select id="getUserList" resultType="com.kuang.pojo.User"> select * from mybatis.user </select> </mapper>
2.4炕桨、測(cè)試
注意點(diǎn):
org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.
MapperRegistry是什么?
核心配置文件中注冊(cè) mappers
-
junit測(cè)試
@Test public void test(){ //第一步:獲得SqlSession對(duì)象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //方式一:getMapper UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> userList = userDao.getUserList(); for (User user : userList) { System.out.println(user); } //關(guān)閉SqlSession sqlSession.close(); }
你們可以能會(huì)遇到的問題:
- 配置文件沒有注冊(cè)
- 綁定接口錯(cuò)誤肯腕。
- 方法名不對(duì)
- 返回類型不對(duì)
- Maven導(dǎo)出資源問題
3献宫、CRUD
1、namespace
namespace中的包名要和 Dao/mapper 接口的包名一致实撒!
2姊途、select
選擇,查詢語句;
- id : 就是對(duì)應(yīng)的namespace中的方法名知态;
- resultType:Sql語句執(zhí)行的返回值捷兰!
- parameterType : 參數(shù)類型!
-
編寫接口
//根據(jù)ID查詢用戶 User getUserById(int id);
-
編寫對(duì)應(yīng)的mapper中的sql語句
<select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User"> select * from mybatis.user where id = #{id} </select>
-
測(cè)試
@Test public void getUserById() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.getUserById(1); System.out.println(user); sqlSession.close(); }
3负敏、Insert
<!--對(duì)象中的屬性贡茅,可以直接取出來-->
<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>
4、update
<update id="updateUser" parameterType="com.kuang.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id} ;
</update>
5原在、Delete
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
注意點(diǎn):
- 增刪改需要提交事務(wù)友扰!
6、分析錯(cuò)誤
- 標(biāo)簽不要匹配錯(cuò)
- resource 綁定mapper庶柿,需要使用路徑村怪!
- 程序配置文件必須符合規(guī)范!
- NullPointerException浮庐,沒有注冊(cè)到資源!
- 輸出的xml文件中存在中文亂碼問題甚负!
- maven資源沒有導(dǎo)出問題!
7审残、萬能Map
假設(shè)梭域,我們的實(shí)體類,或者數(shù)據(jù)庫(kù)中的表搅轿,字段或者參數(shù)過多病涨,我們應(yīng)當(dāng)考慮使用Map!
//萬能的Map
int addUser2(Map<String,Object> map);
<!--對(duì)象中的屬性璧坟,可以直接取出來 傳遞map的key-->
<insert id="addUser" parameterType="map">
insert into mybatis.user (id, pwd) values (#{userid},#{passWord});
</insert>
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("userid",5);
map.put("passWord","2222333");
mapper.addUser2(map);
sqlSession.close();
}
Map傳遞參數(shù)既穆,直接在sql中取出key即可赎懦! 【parameterType="map"】
對(duì)象傳遞參數(shù),直接在sql中取對(duì)象的屬性即可幻工!【parameterType="Object"】
只有一個(gè)基本類型參數(shù)的情況下励两,可以直接在sql中取到!
多個(gè)參數(shù)用Map囊颅,或者注解当悔!
8、思考題
模糊查詢?cè)趺磳懀?/p>
-
Java代碼執(zhí)行的時(shí)候踢代,傳遞通配符 % %
List<User> userList = mapper.getUserLike("%李%");
-
在sql拼接中使用通配符盲憎!
select * from mybatis.user where name like "%"#{value}"%"
4、配置解析
1奸鬓、核心配置文件
mybatis-config.xml
-
MyBatis 的配置文件包含了會(huì)深深影響 MyBatis 行為的設(shè)置和屬性信息焙畔。
configuration(配置) properties(屬性) settings(設(shè)置) typeAliases(類型別名) typeHandlers(類型處理器) objectFactory(對(duì)象工廠) plugins(插件) environments(環(huán)境配置) environment(環(huán)境變量) transactionManager(事務(wù)管理器) dataSource(數(shù)據(jù)源) databaseIdProvider(數(shù)據(jù)庫(kù)廠商標(biāo)識(shí)) mappers(映射器)
2掸读、環(huán)境配置(environments)
MyBatis 可以配置成適應(yīng)多種環(huán)境
不過要記状丁:盡管可以配置多個(gè)環(huán)境,但每個(gè) SqlSessionFactory 實(shí)例只能選擇一種環(huán)境儿惫。
學(xué)會(huì)使用配置多套運(yùn)行環(huán)境澡罚!
Mybatis默認(rèn)的事務(wù)管理器就是 JDBC , 連接池 : POOLED
3肾请、屬性(properties)
我們可以通過properties屬性來實(shí)現(xiàn)引用配置文件
這些屬性都是可外部配置且可動(dòng)態(tài)替換的留搔,既可以在典型的 Java 屬性文件中配置,亦可通過 properties 元素的子元素來傳遞铛铁「粝裕【db.properties】
編寫一個(gè)配置文件
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
在核心配置文件中映入
<!--引入外部配置文件-->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="11111"/>
</properties>
- 可以直接引入外部文件
- 可以在其中增加一些屬性配置
- 如果兩個(gè)文件有同一個(gè)字段,優(yōu)先使用外部配置文件的饵逐!
4括眠、類型別名(typeAliases)
- 類型別名是為 Java 類型設(shè)置一個(gè)短的名字”度ǎ‘
- 存在的意義僅在于用來減少類完全限定名的冗余掷豺。
<!--可以給實(shí)體類起別名-->
<typeAliases>
<typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>
也可以指定一個(gè)包名,MyBatis 會(huì)在包名下面搜索需要的 Java Bean薄声,比如:
掃描實(shí)體類的包当船,它的默認(rèn)別名就為這個(gè)類的 類名,首字母小寫默辨!
<!--可以給實(shí)體類起別名-->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
在實(shí)體類比較少的時(shí)候德频,使用第一種方式。
如果實(shí)體類十分多缩幸,建議使用第二種壹置。
第一種可以DIY別名档叔,第二種則·不行·,如果非要改蒸绩,需要在實(shí)體上增加注解
@Alias("user")
public class User {}
5衙四、設(shè)置
這是 MyBatis 中極為重要的調(diào)整設(shè)置,它們會(huì)改變 MyBatis 的運(yùn)行時(shí)行為患亿。
6传蹈、其他配置
- typeHandlers(類型處理器)
- objectFactory(對(duì)象工廠)
- plugins插件
- mybatis-generator-core
- mybatis-plus
- 通用mapper
7、映射器(mappers)
MapperRegistry:注冊(cè)綁定我們的Mapper文件步藕;
方式一: 【推薦使用】
<!--每一個(gè)Mapper.XML都需要在Mybatis核心配置文件中注冊(cè)惦界!-->
<mappers>
<mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>
方式二:使用class文件綁定注冊(cè)
<!--每一個(gè)Mapper.XML都需要在Mybatis核心配置文件中注冊(cè)!-->
<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
</mappers>
注意點(diǎn):
- 接口和他的Mapper配置文件必須同名咙冗!
- 接口和他的Mapper配置文件必須在同一個(gè)包下沾歪!
方式三:使用掃描包進(jìn)行注入綁定
<!--每一個(gè)Mapper.XML都需要在Mybatis核心配置文件中注冊(cè)!-->
<mappers>
<package name="com.kuang.dao"/>
</mappers>
注意點(diǎn):
- 接口和他的Mapper配置文件必須同名雾消!
- 接口和他的Mapper配置文件必須在同一個(gè)包下灾搏!
練習(xí)時(shí)間:
- 將數(shù)據(jù)庫(kù)配置文件外部引入
- 實(shí)體類別名
- 保證UserMapper 接口 和 UserMapper .xml 改為一致!并且放在同一個(gè)包下立润!
8狂窑、生命周期和作用域
生命周期,和作用域桑腮,是至關(guān)重要的泉哈,因?yàn)殄e(cuò)誤的使用會(huì)導(dǎo)致非常嚴(yán)重的并發(fā)問題。
SqlSessionFactoryBuilder:
- 一旦創(chuàng)建了 SqlSessionFactory破讨,就不再需要它了
- 局部變量
SqlSessionFactory:
- 說白了就是可以想象為 :數(shù)據(jù)庫(kù)連接池
- SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運(yùn)行期間一直存在丛晦,沒有任何理由丟棄它或重新創(chuàng)建另一個(gè)實(shí)例。
- 因此 SqlSessionFactory 的最佳作用域是應(yīng)用作用域提陶。
- 最簡(jiǎn)單的就是使用單例模式或者靜態(tài)單例模式烫沙。
SqlSession
- 連接到連接池的一個(gè)請(qǐng)求!
- SqlSession 的實(shí)例不是線程安全的搁骑,因此是不能被共享的斧吐,所以它的最佳的作用域是請(qǐng)求或方法作用域。
- 用完之后需要趕緊關(guān)閉仲器,否則資源被占用煤率!
這里面的每一個(gè)Mapper,就代表一個(gè)具體的業(yè)務(wù)乏冀!
5蝶糯、解決屬性名和字段名不一致的問題
1、 問題
數(shù)據(jù)庫(kù)中的字段
[圖片上傳失敗...(image-810f04-1587294155346)]
新建一個(gè)項(xiàng)目辆沦,拷貝之前的昼捍,測(cè)試實(shí)體類字段不一致的情況
public class User {
private int id;
private String name;
private String password;
}
測(cè)試出現(xiàn)問題
[圖片上傳失敗...(image-8a3ccf-1587294155346)]
// select * from mybatis.user where id = #{id}
//類型處理器
// select id,name,pwd from mybatis.user where id = #{id}
解決方法:
-
起別名
<select id="getUserById" resultType="com.kuang.pojo.User"> select id,name,pwd as password from mybatis.user where id = #{id} </select>
2识虚、resultMap
結(jié)果集映射
id name pwd
id name password
<!--結(jié)果集映射-->
<resultMap id="UserMap" type="User">
<!--column數(shù)據(jù)庫(kù)中的字段,property實(shí)體類中的屬性-->
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" resultMap="UserMap">
select * from mybatis.user where id = #{id}
</select>
-
resultMap
元素是 MyBatis 中最重要最強(qiáng)大的元素 - ResultMap 的設(shè)計(jì)思想是妒茬,對(duì)于簡(jiǎn)單的語句根本不需要配置顯式的結(jié)果映射担锤,而對(duì)于復(fù)雜一點(diǎn)的語句只需要描述它們的關(guān)系就行了。
-
ResultMap
最優(yōu)秀的地方在于乍钻,雖然你已經(jīng)對(duì)它相當(dāng)了解了肛循,但是根本就不需要顯式地用到他們。 - 如果世界總是這么簡(jiǎn)單就好了银择。