什么是Mybits
是一款优秀的持久层框架,
他是支持制定SQL, 存储过程以及高级映射
.它避免了几乎所有JDBC代码和手动设置参数, 以及获取结果集
是一种可以
- 使用XML或者注解来配置和映射,
- 支持动态sql以及数据缓存
- 将结果映射成java的对象, 是一种ORM(对象关系映射)实现
ORM指,将数据库的记录与java里的对象进行关系映射
- 对jdbc原生的接口进行封装, 提供了一些mybatis自己的接口和类
Mybatis中文官网:点击此处
简而言之: mybatis就是对jdbc功能进行轻量级的封装
1.1、如何获取Mybits
1.2、持久层
Dao层, Service层. Controller层
完成持久化工作的代码块
1.3 为什么需要Mybits
帮助程序员将数据存入数据库里
方便
传统的JDBC代码复杂. 使用框架简化,自动化
优点:
SQL与代码分离, 提高可维护性
提供映射标签, 支持对象与数据库的orm字段关系映射
提供对象关系映射标签, 支持对象关系组织维护
提供xml标签, 支持编写动态SQL
2、 第一个Mybits程序
搭建环境->导入Mybits->编写代码->测试
2.1、搭建环境
<1>搭建数据库
<2>搭建项目
- 新建一个maven项目
- 删除src
- 导入maven依赖
<!--导入依赖-->
<dependencies>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--mybits-->
<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>
<3>junit测试
配置Maven
2.2创建一个模块
●编写mybatis的核心配置文件
●编写mybatis工具类
SqlSession实例包含了面向数据库执行SQL命令的所有方法
2.3、编写代码
●实体类
//实体列
public class User {
private int id;
private String account;
private String password;
public User() {
}
public User(int id, String account, String password) {
this.id = id;
this.account = account;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", account='" + account + '\'' +
", password='" + password + '\'' +
'}';
}
}
●Dao接口
public interface UserDao {
List<User> getUserList();
}
●接口实现类由原来的UserDaoImpl变成一个Mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.jwq.dao.UserDao">
<!--select查询语句-->
<select id="getUserList" resultType="com.jwq.pojo.User ">
select * from chat_room.users
</select>
</mapper>
2.4、 测试
在test包里建测试类UserDaoTest
进行junit测试
注意点:
错误一
org.apache.ibatis.binding.BindingException: Type interface com.jwq.dao.UserDao is not known to the MapperRegistry.
MapperRegistry.是什么?
对于接口里写的.xml文件
此时会报错
由于编译后的文件没有.xml文件所以要
在核心配置文件里头注册mappers
Mybatis核心配置文件注册应该是resource="com/jwq/dao/UserMapper.xml"才对
错误二
java文件里的.xml文件不能导出,应该放到rsouces下
在指定的pom文件里头
3、CRUD(对数据操作:增删改查)
3.1、namespace
namespace中的包名必须和Dao/mapper接口的包名一致
3.2、select
●id:就是对应的namespace接口中的方法名;
●resultType:Sql语句执行的返回值;
●parameterType: 参数类型!
指定接口里写对应查询方法:
Mapper.XML文件里头要绑定实现对应方法
在Test里测试
注意点:在执行增删改时候,要提交事务
4、万能Map
假设,我们的实体类,或者数据库里的表,字段或者参数过多,我们应当考虑使用Map!!!
接口 与 对应mapper里的写法
对象与Map传递总结:
Map传递参数,直接在sql中取出key即可!【paremeterType=“map”】
对象传递参数,直接在sql中取对象的属性!【paremeterType=“Object”】
在只有一个基本类型参数情况下,可以直接在sql取到
多个参数用Map,或者注解Mapper测试方法
5、模糊查询:
在模糊查询的时候,要注意sql注入问题
所以就会存在安全问题
模糊查询方法
- java执行代码时候,传递通配符% 模糊字段 %
List userList = mapper.getUserLike(%李%)- 在sql拼接中使用通配符
select * from mybatis.user where name like "%#{value}%"在sql里头直接拼接% %(通配符)就可以,只让用户传入查询的指定字段,就解决sql注入的安全问题
例子:
- 首先接口里写指定方法
- 指定的Mapper.xml文件里绑定实现对应方法
6、配置文件
●mybatis-config.xml文件
●mybatis的配置文件包含了会深深印象MyBatis行为的设置和属性信息
注意:配置时候,标签必须按照一定的顺序进行排序,不然就报错
如下:
6.1、配置环境enviroments
6.2、引入外部配置文件properties
核心配置文件
对应的properties
注意:如果在核心配置文件与外部的properties出现冲突值,会优先使用外部的properties的信息
6.3、给实体类起别名typeAlias
在对用的XML文件里绑定实现对应方法,设置返回类型时候,可以使用别名
- 对应实体类起别名
- 扫描实体类的包,默认别名是类名,小写(也可以大写)
pojo下有类User别名就是user
扫描包情况下,可以使用注解来起别名
6.4、映射器mappers
MapperRegistry:注册绑定我们的Mapper文件
方式一:使用resource绑定对应的xml
方式二:使用class绑定xml文件
class配置时,要满足:
- 接口和他的Mapper配置文件必须同名
- 接口和他的Mapper配置文件必须在同一个包下面
方式三:使用扫描包进行注入绑定
# 7、解决属性名与字段名不一致问题
>如果属性是password,字段名是pwd的话
>
>查询出来,对应的字段名是空(null)
解决:
1. 起别名![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/60e44170a48d421ca58bd4ca962b6afa.png)
2. 使用映射标签
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/04488e960f8448e8af6b58cfb8e44137.png)
# 8、日志
>如果一个数据库,出现了异常,我们就需要排错,日志就是最好帮手;
8.1设置日志:
在Mybatis中具体使用哪一个日志,在设置里设定!
需要在mybatis的核心配置文件里进行配置日志
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/55bb566e356f448899f440a960d88765.png)
8.2、Log4j
什么是logj?
>1. 他是Apache的一个开源项目,通过使用logj,我们可以控制日志信息输送的目的地是控制台,文件,GUI组件
>2. 可以控制每一条日志的输出格式
>3. 通过定义每一条日志信息的级别,能更加细致的控制日志的生成过程
>4. 可以通过配置文件来灵活进行配置,而不需要修改应用代码
<1>先导入log4j的包
*在pom.xml导入*
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/02f7291f6b3845a08f22690d80d49848.png)
<2>新建外部配置文件log4j.properties
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/7c36125c389a41e5b2095195c86d0fd3.png)
<3>配置log4j 为日志的实现
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/aa1daf840ef54e5a8b09c031229b0c18.png)
**简单使用**
1. 在要使用logj的类中,导入包 import org.apache.log4j.Logger;
2. 传入日志对象,是当前类的class
static Logger logger = Logger.getLogger(UserDaoTest.class)
3. 设置日志级别
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/32a34b2a750e49e7b76381dc1f29b172.png)
# 9、分页
为什么要分页?
减少数据的处理量
9.1、使用Limit实现分页
![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/8c3816e208c0429c84df4bd4c50b8139.png)
```曾经在Mybatis历史上,当传入第二个参数是-1时候,会查询第一个参数到结尾的数据,但是后来被修复了
使用Mybatis实现分页(还是使用sql语句)
- 接口
- Mapper.xml
- 测试
9.2、RowBounds分页(了解)
不再使用SQL实现分页
- 接口
- mapper.xml
- 测试
10、使用注解开发
10.1、注解使用
- 注解在接口上实现
- 需要在核心配置文件中绑定接口
- 测试
10.2、注解增删改查
这样增删改时候,就不用提交事务
注意:当使用多个参数时,就要加上注解标签
@Param
关于@Param()注解
●基本类型或者String类型,需要加上
●引用类型不需要加
●如果只有一个基本类型不用加(建议加)
●在SQL里引用的就是我们这里的@Param()设定的属性名
关于#{}与${}区别
●#{}可以有效防止SQL注入问题
●他俩关系就好像JDBC里的Praparment与PraparStatement
11、Lombok
他是一个java库,它可以自动插入编辑器并构建工具
不用再写getter或者equals方法,可以用一个注释可以实现、
使用步骤:
在IDEA中安装Lombok插件!
在项目pom.xml中导入lombok的jar包
使用注解
@Data:无参构造,get,set,tostring,hashcode,equals
@AllargsConstructor :有参构造
@NoAllargsConstructor :无有参构造
@EqualsAnHashCode
@ToString
@Getter
12、 数据库数据对应关系
多对一数据
建表:
写具体的pojo(实体类对应字段)
写对应pojo的接口
导入核心配置文件
根据学生、老师表,查询学生里(tid)与之对应的老师
对应Mapper一
对应Mapper二
Mapper一与Mapper二都可以
对应结果
一对多数据
构建实体类
对应Mapper
按照结果嵌套处理
按照子查询处理
上图的子查询嵌套处理补全
总结:
- 对象关联-association【多对一】
- 集合-collection【一对多】
- javaType&&ofType
javaType:用来指定实体类中属性的类型
ofType:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
13、动态SQL
就是根据不同条件生成不同的SQL语句
动态SQL元素和JSTL或基于类似的XML的文本处理器相似. 在Mybatis之前的版本中, 有很多元素需要花时间了解. Mybatis 3 大大精简了元素种类, 现在只需要学习原来一半元素即可. Mybatis 采用功能强大的基于OGNL的表达式来淘汰其他大部分元素
- if
- choose(when, otherwise)
- trim(where, set)
- foreach
搭建环境
创建一个基础工程
导包
编写配置文件
编写实体类
public class Blog { private int id; private String title; private String author; private Data createTime; private int views; }
编写实体列对应Mapper接口和Mapper.XML文件
**
IF
**
<select id="queryBlog" parameterType="map" resultType="blog">
select * from chat_room.blog where 1=1
<if test="title!=null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
上述代码,如果没有title, 有author, 就会将 and author = #{指定author}自动拼接进去SQL语句,所以就要在合适情况下加上and,不合适情况下不加and,就要用where标签实现
choose(when, otherwise)
when:
当传入一个或者多个条件时候会根据条件数量来自动选择是否拼接when或者andchoose
当传入多个判断条件时候,choose会选择choose里的第一个when,不传就查询所有
trim(where, set)
where
set
自动去出update数据最后一个逗号,如果没有传入对应的参数就会报错即以下逗号
注意:
最好基于单表来定义sql片段
不要存在where标签
foreach
是对一个集合进行遍历,通常在需要加入条件语句时候,就需要foreach来优化
此处穿一个万能的map,map里可以放一个集合!!
综上:动态sql就是拼接SQL语句,保证sql的正确性,按照格式,去组合
14、缓存
简介:
查询 : 连接数据库, 耗资源!
一次查询的结果, 可以暂存在一个可以直接取到的地方!---->即内存里(也叫缓存)
当我们再次查询的时候,就直接走缓存, 就不用再走数据库
优点:
将用户经常查询的数据放缓存里,再次去查询就不用从磁盘上查, 直接从缓存查, 可以提高查询效率, 解决高并发系统的性能问题
这样可以减少与数据库交互的次数, 减少系统开销, 提高系统效率
在经常使用的且不经常改变的数据上可以使用缓存
14.1、Mybatis缓存
Mybatis系统中默认定义两级缓存, 一级缓存和二级缓存
默认情况, 一级缓存是开的(Sqlsession级别的缓存,也叫本地缓存)
二级缓存需要手动开启配置, 他是基于namespace级别的缓存
为了提高扩展性, Mybatis定义了缓存接口Cache. 可以实现Cache接口来自定义二级缓存
一、一级缓存
也叫做本地缓存,sqlSession
与数据库同一次会话期间查询到的数据会放到本地缓存中
以后如果要获取相同的数据, 就直接从缓存里拿, 没必要再去查询数据库
日志输出
缓存失效情况:
- 查询不同的东西
增删改操作, 可能会改变原来的数据, 所以必定会刷新缓存
查询不同的Mapper.xml
- 手动清理缓存
小结:一级缓存默认是开启的, 只在一次SqlSession中有效, 也就是拿到连接到关闭这个区间段!
二、二级缓存
也叫全局缓存,一级缓存作用域低, 所以诞生二级缓存
基于namespace级别的缓存, 一个名称空间,对应一个二级缓存
工作原理:
如果当前的会话关闭了, 这个会话对应的一级缓存就没了; 但是我们想要的是, 会话关闭了, 一级缓存数据保存到二级缓存里
新的会话查询信息,就可是直接从二级缓存里获取内容
不同的mapper查出的数据会放在自己对应的缓存中
开启二级缓存测试:
问题抛出
- 我们需要将实体类序列化!否则就会报错
就是将对应的pojo实体列实现接口
小结:
只要开启了二级缓存,在同一个Mapper下就有效
所有的数据都是先放到一级缓存中
只有当会话提交,或者关闭时候,才会提交到二级缓存里
一二级缓存,数据库查询顺序
首先先到二级缓存里找, 找不到再到一级缓存里找, 最后找不到在连接数据库
如图: