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
```
? 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
```
#### 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
}
```
##### 接口实现类由原来的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
```
#### 8,模糊查询
1,java代码执行的时候,传递通配符%
```java
List
```
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的类中,导入包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
```
#### 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
}
```
Mapper
```java
Teacher getTeacher(@Param("tid") int tid);
Teacher getTeacher2(@Param("tid") int tid);
```
方式一
```xml
```
方式二
```xml
```
#### 17,动态SQL
根据不同条件生成不同SQL语句
```java
List
List
int updateBlog(Map map);
```
**if**
```xml
```
**choose,when**,**otherwise**
```xml
```
**trim,where,set**
```xml
update mybatis.blog
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
```