【Mybatis】笔记
一、Mybatis简介
1.1、Mybatis
- MyBatis是一款优秀的持久层框架
- MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
1.2、持久化
持久化就是将程序的数据在持久状态和瞬时状态转化的过程
为什么需要需要持久化?
1、有一些对象,不能让他丢掉。
2、内存太贵了
1.3、持久层
Dao层,Service层,Controller层…
完成持久化工作的代码块
层界限十分明显。
2、一个mybatis程序
2.1、搭建环境
2.1.1、创建数据库
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 80018
Source Host : localhost:3306
Source Schema : mybatis
Target Server Type : MySQL
Target Server Version : 80018
File Encoding : 65001
Date: 01/01/2022 22:30:57
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`pwd` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '张三', '123456');
INSERT INTO `user` VALUES (2, '李四', '123456');
INSERT INTO `user` VALUES (3, '王五', '123456');
SET FOREIGN_KEY_CHECKS = 1;
2.1.2、 新建项目导入依赖
<!--导入依赖-->
<dependencies>
<!--mysqL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
2.2、创建模块
2.2.1、编写mybatis的核心配置文件
mybatis-config.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?&useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/demo01/dao/UserMapper.xml" />
</mappers>
</configuration>
2.2.2、编写mybatis工具类
mybatisutils
package com.demo01.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
//sqLsessionFactory
public class mybatisutils {
public static SqlSessionFactory sqlSessionFactory;
static{
//使用Mybatis第一步获取SqlSessionFactory对象
try {
String resource = "mybatis-config.xml" ;
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqLSessionFactory,顾名思义,我们就可以从中获得SqLSession 的实例了
// sqLSession完全包含了面向数据库执行 sQL命令所需的所有方法。
public static SqlSession getSqlSession(){
SqlSession sqlSession=sqlSessionFactory.openSession();
return sqlSession;
}
}
2.3、编写代码
实体类 User
package com.demo01.pojo;
@Data
public class User {
private int id;
private String name;
private String pwd;
}
Dao接口 UserDao
package com.demo01.dao;
import com.demo01.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
}
接口实现类 UserMapper.xml
<?xm1 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.demo01.dao.UserDao">
<select id="getUserList" resultType="com.demo01.pojo.User">
select * from mybatis.user;
</select>
</mapper>
2.4、测试
test
package com.demo01.dao;
import com.demo01.pojo.User;
import com.demo01.utils.mybatisutils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
//第一步:获得SqLsession对象
SqlSession sqlsession = mybatisutils.getSqlSession();
//执行sql
UserDao userDao=sqlsession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user.getId());
}
//关闭SqLsession
sqlsession.close();
}
}
在junit里测试时 正常是不会扫描到src里的文件 添加下面代码进行全局扫描
<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>
3、增删查改
3.1、属性
3.1.1、参数
- namespace中的包名要和Dao/mapper接口的包名一致!
- id 就是对应的namespace中的方法名
- resultType: Sql语句执行的返回值!
- parameterType :参数类型!
3.1.2、select
- 编写接口
//根据ID查询用户
User getUserById(int id);
- 编写mapper中的sql语句
<select id="getUserById" parameterType="int" resultType="com.demo01.pojo.User">
select * from mybatis.user where id = #{id}
</select>
- 测试类
public void getUserById(){
SqlSession sqlsession = mybatisutils.getSqlSession();
UserDao mapper = sqlsession.getMapper(UserDao.class);
User user = mapper.getUserById(1);
System.out.println(user.getName());
sqlsession.close();
}
3.1.3、insert
- 编写接口
//插入User
int addUser(User user);
- 编写mapper中的sql语句
<insert id="addUser" parameterType="com.demo01.pojo.User">
insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>
- 测试类
public void addUser(){
SqlSession sqlsession = mybatisutils.getSqlSession();
UserDao mapper = sqlsession.getMapper(UserDao.class);
int res = mapper.addUser(new User(4,"哈哈","123333"));
if (res>0){
System.out.println("插入成功!");
}
//提交事务
sqlsession.commit();
sqlsession.close();
}
3.1.4、update
- 编写接口
//修改User
int updateUser(User user);
- 编写mapper中的sql语句
<update id="updateUser" parameterType="com.demo01.pojo.User">
update mybatis.user
set name=#{name},pwd=#{pwd}
where id=#{id};
</update>
- 测试类
public void updateUser(){
SqlSession sqlsession = mybatisutils.getSqlSession();
UserDao mapper = sqlsession.getMapper(UserDao.class);
int res =mapper.updateUser(new User(4,"嘿嘿","123333"));
if (res>0){
System.out.println("修改成功!");
}
//提交事务
sqlsession.commit();
sqlsession.close();
}
3.1.5、delete
- 编写接口
//删除User
int delUser(int id);
- 编写mapper中的sql语句
<delete id="delUser" parameterType="int">
delete
from mybatis.user
where id=#{id}
</delete>
- 测试类
public void delUser(){
SqlSession sqlsession = mybatisutils.getSqlSession();
UserDao mapper = sqlsession.getMapper(UserDao.class);
int res= mapper.delUser(4);
if (res>0){
System.out.println("删除成功!");
}
//提交事务
sqlsession.commit();
sqlsession.close();
}
3.1.6、注意点
增删改需要提交事务sqlsession.commit();
3.2、Map类型传递
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map
int adduser2 (Map<String,Object> map);
使用map不需要和类型里的参数对应,需要与Map的key对应即可
<insert id="addUser2" parameterType="map">
insert into mybatis.user (id,name,pwd) values (#{userId},#{userName},#{userPassword});
</insert>
3.3、模糊查询
List<User> getUserLike();
4、配置解析
4.1、配置属性
MyBatis的配置文件包含了影响MyBatis行为的设置和属性信息
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory (对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器>
datasource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
4.2、环境配置(environments)
MyBatis可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择一种环境
Mybatis默认的事务管理器就是JDBC,连接池:POOLED
4.3、属性(properties)
我们可以通过properties属性来实现引用配置文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?&useSSL=false&serverTimezone=UTC
username=root
password=root
- 可以直接引入外部文件
- 可以在其中增加一些属性配置
- 如果两个文件有同一个字段,优先使用外部配置文件的!
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="root"/>
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
4.4、类型别名(typeAliases)
类型别名是为Java类型设置一个短的名字。它只和XML配置有关
存在的意义仅在于用来减少类完全限定名的冗余.
<typeAliases>
<typeAlias type="com.demo02.pojo.User" alias="User"/>
</typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的Java Bean,比如:
扫描实体类的包,它的默认别名就为这个类的类名,首字母小写
<typeAliases>
<package name="com.demo02.pojo"/>
</typeAliases>
<select id="getUserList" resultType="user">
不想使用扫包默认的别名亦可以使用注解别名
@Alias("User")
4.5、设置(settings)
这是MyBatis 中极为重要的调整设置,它们会改变MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。
4.6、生命周期与作用域
生命周期,和作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题
SqlSessionFactoryBuilder:
- 一旦创建了SqlSessionFactory,就不再需要它了
- 局部变量
SqlSessionFactory:
- 说白了就是可以想象为︰数据库连接池
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
- 因此SqlSessionFactory的最佳作用域是应用作用域。
- 最简单的就是使用单例模式或者静态单例模式。
SqlSession:
- 连接到连接池的一个请求!
- SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
- 用完之后需要赶紧关闭,否则资源被占用!
5、结果集映射(ResultMap)
<!--结果集映射-->
<resultMap id="UserMap" type="User">
<!--coLumn数据库中的字段,property实体类中的属性-->
<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 = #{fid}
</select>
- resultMap 元素是MyBatis中最重要最强大的元素
- ResultMap的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。