Mybatis
持久层框架,方便填写sql语句
方便,帮助将数据存入数据库
传统的JDBC代码太复杂。简化、框架、自动化。
优点
- 简单易行
- 灵活
- sql和代码的分离,提高了可维护性
- 。。。
持久化
数据持久化
- 持久化就是将程序的数据在持久状态和顺势状态转化的过程
- 内存:断电即失
- 数据库(Jdbc),io文件持久化
持久层
Dao层,Service层,Controller层
- 完成持久化工作的代码块
- 层界限十分明显
1. Mybatis程序
1.1 搭建环境
- 搭建数据库
create database `mybatics`;
use mybatics;
create table `user`(
`id` int(20) not null,
`name` varchar(30) default null,
`pwd` varchar(30) default null,
primary key(`id`)
)engine=InnoDB default charset=utf8;
insert into `user`(`id`,`name`,`pwd`) values
(1,'张三','123456'),
(2,'李四','123456'),
(3,'王五','123456') 新建项目
- 创建maven项目
- 更换自己的maven仓库
- 删除src目录
- 导入maven依赖
<dependencies>
<!-- mysql驱动 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- mybatis -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- junit -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies> 1.2 创建模块
idea数据库连接
问题:
mysql8.0 需要重新导入8.0的jdbc的jar包
serverTimezone未配置
- 打开mysql命令行
// 显示时区信息 show variables like’%time_zone’; // 若显示为system --> 表示未设置时区 //设置时区 set global time_zone=’+8:00’;
编写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.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatics?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="888888"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>编写mybatis工具类
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 --> sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
try {
//第一步:获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (IOException e){
e.printStackTrace();
}
}
//从sqlSessionFactory获取sqlSession实例
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
1.3 编写代码
- 实体类
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();
} - 接口实现类 : 由原来的Dap实现类重写方法的方式转为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">
<!-- 绑定一个对于的Mapper接口 -->
<mapper namespace="com.Rickduck.dao.UserDao">
<!--select查询语句-->
<select id="getUserList" resultType="com.Rickduck.pojo.User">
select * from mybatis.user
</select>
</mapper> 1.4 测试
核心配置中配置mapper
junit单元测试
package com.Rickduck.dao;
import com.Rickduck.pojo.User;
import com.Rickduck.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;
import java.util.List;
public class MyTest {
@Test
public void test(){
//第一步:获得SqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
//执行Sql
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
需要注意的问题
- 配置文件是否已有注册
- 绑定接口是否有错
- 方法名是否有错
- 返回类型是否正确
- Maven导出资源是否有问题
- SqlSessionFactoryBuilder
- 负责创建SqlSessionFactory,一旦创建了SqlSessionFactory,就不再需要用它
- 方法作用域(局部方法变量)
- SqlSessionFactory
- 创建SqlSession,一旦被创建就应该在应用的运行期间一直存在
- 应用作用域(单例模式或静态单例模式)
- SqlSession
- 每个线程应该都有自己的SqlSession实例
- 线程不安全
- 请求或方法作用域
- 每收到HTTP请求,就可以打开SqlSession,返回一个响应,就关闭
- 关闭操作放在finall块中!!!
另外关于资源配置的问题:
<!-- 在build中配置resources,来防止我们资源导出失败的问题 -->
<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>
2. CRUD
1.namespace
namespace中的包名跟Mapper接口的包名一致
2. select
选择、查询语句
- id : 方法名
- resultType : Sql语句执行的返回值
- parameterType : 参数类型
//第一步:获得SqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
//执行Sql
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
@Test
public void select(){
try{
// 1. select *
List<User> userList = userMapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
//2. selecById
User user = userMapper.getUserById(1);
System.out.println(user);
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭sqlSession
sqlSession.close();
}
}
3. insert(增删改 需要提交事务)
@Test
public void insertTest(){
//3. insert (增删改需要提交事务)
int flag = userMapper.addUser(new User(4,"哈哈","123456"));
//事务提交
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
}
4. update
5. delete
6.Map
实体类或数据库中的表、字段或者参数过多,可以考虑使用Map!
3. 配置解析
1.核心配置文件
mybatis-config.xml
MyBatis的配置文件会深深影响Mybatis星为的设置和属性信息
properties(属性) settings(设置) typeAliases(类型别名) typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) environments(环境配置) environment(环境变量) transactionManager(事务管理器) dataSource(数据源) databaseIdProvider(数据库厂商标识) mappers(映射器)
2. 环境配置
可以配置多个环境,但每个sqlSessionFactory实例只能选择一个环境
默认事务管理器:JDBC
默认连接池:POOLED
3. 属性(properties)
可以通过properties属性实现引用配置文件(内部优先)
- 属性可外部配置动态替换
<!-- 引入外部配置文件 -->
<properties resource="db.properties" >
<property name="username" value=""/>
<property name="password" value=""/>
</properties>
4. 类型别名
- 实体类
- 包扫描
- 注解(实体类上添加@Alias("name") )
<typeAliases>
<!-- 实体类起别名 -->
<typeAlias type="com.Rickduck.pojo.User" alias="User" />
<!-- 包扫描起别名-->
<package name="com.Rickduck.pojo"/>
</typeAliases>
5. 设置
6. 映射器
MapperRegistry : 注册绑定我们的映射文件
方式一: xml配置
<mappers>
<mapper resource="com/Rickduck/dao/UserMapper.xml"/>
</mappers>
方式二: class文件绑定注册
<mappers>
<mapper class="com.Rickduck.pojo.UserMapper" />
</mappers>
注意点:
- 接口和Mapper配置文件必须同名
- 接口和Mapper配置文件必须在同一包下
方式三:使用包扫描
<mappers>
<package name="com.Rickduck.pojo"/>
</mappers>
注意点:
- 接口和Mapper配置文件必须同名
- 接口和Mapper配置文件必须在同一包下
7. 生命周期和作用域
SqlSessionFactoryBuilder
- 一旦创建就不再需要
- 最佳作用域:局部变量
SqlSessionFactory
- 一旦创建旧应该一直存在(类似连接池)
- 最佳作用域:应用作用域
- 单例模式/静态单例模式
SqlSession
连接到连接池的一个请求
SqlSession非线程安全,不能被共享
最佳作用域:请求或方法作用
用完后断开
4. 解决属性名和字段名不一致的问题
resultMap
结果集映射
<mapper namespace="com.Rickduck.dao.UserMapper">
<!-- pojo类与数据库名字不一致可一一映射 -->
<!-- 结果集映射 -->
<resultMap id="UserMap" type="User">
<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>
</mapper>
ResultMap设计思想:对于简单语句不需要配置显示映射,复杂语句只需要描述他们的关系即可
5. 日志
5.1 日志工厂
- 出现异常、排错 需要日志!!
- 曾经:sout、debug
- 现在:日志工厂!
1609925677993
- mybatis-config.xml 在properties中添加:
- STDOUT_LOGGING : 标准日志输出
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings> 5.2 Log4J
- log4J:可以控制日志信息的输出位置(控制台,组件,文件)
- 可以控制
输出格式 - 可以定义日志的
级别,更加细致控制日志的生成过程 - 可通过一个
配置文件配置而无需修改代码
- 导入log4j的包
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.0</version>
</dependency> - log4j.properties
- 配置log4j为日志实现
<settings>
<setting name="logImpl" value="LOG4J" />
</settings> - log4j的使用 测试运行
简单使用
在需要使用log4j的类中,导入包
import org.apache.log4j.logger日志对象,参数为当前类的class
//日志对象
static Logger logger = Logger.getLogger(UserMapper.class);
public void testLog4j(){
logger.info("info");
logger.debug("debug");
logger.error("error");
} - 日志级别
logger.info("info");
logger.debug("debug");
logger.error("error"); 6. 分页
6.1 使用Limit分页
- 减少数据的处理量
- 使用
limit进行分页
-- 语法:select * from user limit startIndex,pageSize; select * from user limit 0,2;
利用Mybatis实现分页,核心SQL
- 接口
List<User> getUserByLimit(Map<String,Integer> map);
- Mapper.xml
<select id="getUserByLimit" parameterType="map" resultType="User">
select * from student.user limit #{startIndex},#{pageSize}
</select> - 测试
@Test
public void getUserByLimit(){
//第一步:获得SqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
//执行Sql
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Integer> map = new HashMap<>();
map.put("startIndex",0);
map.put("pageSize",2);
List<User> userList = userMapper.getUserByLimit(map);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
} 6.2 通过RowBound实现分页
- 接口
List<User> getUserByRowBounds();
- mapper.xml
<select id="getUserByRowBounds" resultMap="UserMap"> select * from mybatis.user </select>
6.3 分页插件
8. 使用注解开发
8.1 面向接口编程
- 根本原因:解耦
三个面向区别
- 面向对象 :以对象为单位,考虑其属性及方法
- 面向过程 :以具体流程(事务过程)为单位,考虑其实现
- 接口设计与非接口设计是针对复用技术而言,更多体现对系统的整体架构
8.2 使用注解开发
是可以使用Java注解来配置
public interface UserMapper{
@Select("select * ftom student.user")
List<User> getUsers();
} 


京公网安备 11010502036488号