MyBatis学习


### Mybatis

环境:

? jdk1.8

? Mysql5.7

? maven:3.6.1

? idea

SSM框架:配置文件

#### 1,简介

1,1 什么是Mybatis

? MyBatis 是一款优秀的**持久层**框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

(本是apache的一个开源项目iBatis,2013年迁移到github)

? 如何获得Mybatis

? Maven库:

```xml


org.mybatis
mybatis
3.5.5

```

? GitHub:https://github.com/mybatis/mybatis-3

? 中文文档:https://mybatis.org/mybatis-3/zh/index.html

#### 1,持久层

数据持久化

? 持久化就是将程序在持久状态和瞬时状态转化的过程

? 内存:断电即失

? 数据库(jdbc),io文件持久化。

#### 2,新建项目

? 1,新建一个普通maven项目

? 2,删除src目录(将当前项目作为父工程)

? 3,导入Maven依赖

```xml




mysql
mysql-connector-java
5.1.47




org.mybatis
mybatis
3.5.5



junit
junit
4.12


```

#### 3,新建模块

编写mybatis的核心配置文件

```xml
<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
















```

编写mybatis工具类

#### 4,编写代码

##### 实体类

```java
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/Mapper接口

```java
public interface UserDao {
List getUserList();
}
```

##### 接口实现类由原来的UserDaoImpl转变为一个Mapper配置文件

```xml
<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">






```

#### 5,测试

注意点:

```java
org.apache.ibatis.binding.BindingException: Type interface com.xiao.dao.UserDao is not known to the MapperRegistry.
```

MapperRegistry:核心配置文件中配置Mapper

```xml



```

```java
Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration
```

#### 6,CRUD

##### 1,namespace

? namespace中的包名要和Dao/Mapper的包名一样

##### 2,select

? 选择,查询语句

? id:就是对应的namespace中的方法名

? resultType:Sql语句执行的返回值

? parameter:参数类型

? 编写接口

```xml
User selectUser(int id);
```

? 编写对应的Mapper中的Sql语句

```xml

```

? 测试

```
@Test
public void queryTest(){
SqlSession sqlSession=MybatisUtils.getSqlSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUser(2);
System.out.println(user);

sqlSession.close();
}
```

##### 3,Insert

```xml

insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});

```

##### 4, update

```xml

update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}

```

##### 5, delete

```xml

delete from mybatis.user where id = #{id}

```

注意点:增删改需要提交事务。

? 多个参数可以用Map

#### 7,常见错误

标签要匹配正确

resource绑定mapper,需要使用路径。( / )

NullPointException,没有注册到资源。变量

输出的xml文件中存在中文乱码的问题。右下角查看编码

maven资源导出问题,pom文件加上:

```xml



src/main/resources

**/*.properties
**/*.xml

true


src/main/java

**/*.properties
**/*.xml

true



```

#### 8,模糊查询

1,java代码执行的时候,传递通配符%

```java
List userList=userMapper.getUserLikeName("%王%");
```

2,在sql拼接中使用通配符

```xml

```

#### 9,配置

##### 1,核心配置文件

mybatis-config.xml

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

- configuration(配置)
- [properties(属性)](https://mybatis.org/mybatis-3/zh/configuration.html#properties)
- [settings(设置)](https://mybatis.org/mybatis-3/zh/configuration.html#settings)
- [typeAliases(类型别名)](https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases)
- [typeHandlers(类型处理器)](https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers)
- [objectFactory(对象工厂)](https://mybatis.org/mybatis-3/zh/configuration.html#objectFactory)
- [plugins(插件)](https://mybatis.org/mybatis-3/zh/configuration.html#plugins)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- [databaseIdProvider(数据库厂商标识)](https://mybatis.org/mybatis-3/zh/configuration.html#databaseIdProvider)
- [mappers(映射器)](https://mybatis.org/mybatis-3/zh/configuration.html#mappers)

##### 2,环境配置

Mybatis可以配置适应多种环境

注意:尽管可以配置多个环境,但是每个SqlSessionFactory只能用一种

Mybatis默认的事务管理是JDBC,默认开启连接池POOLED

##### 3,属性

编写个配置文件

```properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username=XIAO
password=XIAO3363138
```

核心配置文件中映入

```xml




```

**可以直接引入外部配置文件**

**可以在其中增加一些属性**

**如果两个文件有相同字段,优先使用外部配置文件**

##### 4, 类别名

1. 类别名是为java类型设置的一个短的名称。

2. 存在的意义仅在于用来减少类完全限定名的冗余

```xml



```

3. 也可以指定一个包名,Mybatis会在包名下面搜索需要的java Bean,比如

扫描实体类的包,他的默认别名就为这个类的类名,首字母小写

```xml



```

在实体类比较少的时候,使用第一种方式。

如果实体类比较多,建议使用第二种

第一种可以DIY别名,第二种则不行,如果非要改,需要在实体类上加注解

```java
@Alias("hello")
public class User {}
```


##### 5,映射器

MapperRegistry:注册绑定Mapper文件

方式一:

```xml



```

方式二:

```xml



```

注意点:

? 接口和他的Mapper配置文件必须同名

? 接口和他的Mapper配置文件必须在同一个包下

方式三:

```xml



```

注意点:

? 接口和他的Mapper配置文件必须同名

? 接口和他的Mapper配置文件必须在同一个包下

#### 10,作用域

生命周期,作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题

**SqlSessionFactoryBuilder**:

一旦创建了SQLSessionFactory,就不再需要它了

局部变量

**SQLSessionFactory**:

? 可以想象为数据库连接池

? SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,**没有任何理由丢弃它或重新创建另一个实例**

? 因此SQLSessionFactory的最佳作用域是应用作用域

? 最简单的使用就是使用单例模式

**SQLSession:**

? 连接到连接池的一个请求

? 关闭

? 不是线程安全的,因此不能被共享,所以最佳的作用域是请求或方法作用域

? 用完后需要赶紧关闭,否则资源被占用

? SQLSession里每获得的一个Mapper,就相当于一个具体的业务

#### 11,解决属性名和字段不一样的问题

ResultMap(结果集)

```xml



```

#### 12,日志

1. 日志工厂

如果一个数据库操作,出现了问题,我们需要排错,日志就很重要

loglmpl:

SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING

在mybatis核心配置文件中配置

```xml



```

##### log4j

使用前先导入包

```xml

log4j
log4j
1.2.12

```

在使用Log4j的类中,导入包import org.apache.log4j.Logger;

日志对象,参数为当前类class

```java
static Logger logger = Logger.getLogger(UserMapperTest.class);
```

日志级别

```java
logger.info("info;");
logger.debug("debug;");
logger.error("error;");
```


#### 13,分页

目的:减少数据量处理

使用limit分页

```xml

```

接口

```java
List getUser(Map map);
```

#### 14,注解开发

在接口上实现

```java
@Select("select * from user where name = #{name}")
User getUserByName(String name);
```

需要在核心配合文件中绑定接口

```xml

```

1. 注解CRUD

```java
@Select("select * from user where id = #{id}")
User getUserById(int id);
@Insert("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
int addUser(User user);
@Delete("delete from user where id = #{id}")
int deleteUser(int id);
@Update("update user set name=#{name},pwd=#{pwd} where id =#{id}")
int updateUser(@Param("id") int id,@Param("name") String name,@Param("pwd") String pwd);
```

注意:

```java
public static SqlSession SqlSessionGet() {
return sqlSessionFactory.openSession(true);
}
```

openSession直接设置为true可以自动提交事务

**关于@Param()**

基本类型和String类型需要加上

引用类型不需要加

如果只有一个基本类型的话,可以忽略,但建议加上

我们在SQL中引用的就是@Param中的属性名

#### 15,多对一查询

```java
Student getStudentByID(int id);
```

方式一:

```xml








```

方式二:

```xml





```

#### 16,一对多查询

POJO

```java
public class Teacher {
private int id;
private String name;
List students;
}
```

Mapper

```java
Teacher getTeacher(@Param("tid") int tid);
Teacher getTeacher2(@Param("tid") int tid);
```

方式一

```xml










```

方式二

```xml





```

#### 17,动态SQL

根据不同条件生成不同SQL语句

```java
List queryBlog(Map map);
List queryBlog2(Map map);
int updateBlog(Map map);
```

**if**

```xml

```

**choose,when**,**otherwise**

```xml

```

**trim,where,set**

```xml

update mybatis.blog

title=#{title},
author=#{author},

where id = #{id}

```

测试时title或author附一个值,不然会报错

**sql标签**

```xml


and title = #{title}



```

#### 18,缓存

1. 什么是缓存【Cache】?

存在内存中的临时数据

将用户经常查询到的数据存放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中从而提高效率,解决了高并发系统性能问题

2. 为什么使用缓存

减少和数据库交互次数,减少系统开销,提高系统效率

3. 什么样数据适合使用缓存

经常查询且不改变的数据

**MyBatis缓存**

MyBatis系统中定义了两级缓存:一级缓存和二级缓存

? 默认情况下,只有一级缓存开启。(SQLSession级别的缓存,也称为本地缓存)

? 二级缓存需要手动开启和配置,他是基于namespace级别的缓存

? 为了提高扩展性,MyBatis定义了缓存接口Cache,我们可以通过实现Cache来定义二级缓存接口

缓存Cache配置:

1.核心文件中的属性配置:开启全局缓存

```xml

```

2.在Mapper.xml文件中添加标签

注意:如果readOnly为false,此时要结果集对象是可序列化的。实现Serialization接口

```xml

```