它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低.
Mybatis官方文档
GitHub地址
持久化是什么
持久化是将程序数据在持久状态和瞬时状态间转换的机制。
为什么需要持久化服务呢?那是由于内存本身的缺陷引起的
持久层又是什么呢
ORM是啥?
Object Relation Mapping,对象关系映射。对象指的是Java对象,关系指的是数据库中的关系模型,对象关系映射,指的就是在Java对象和数据库的关系模型之间建立一种对应关系,比如用一个Java的Student类,去对应数据库中的一张student表,类中的属性和表中的列一一对应。Student类就对应student表,一个Student对象就对应student表中的一行数据
那么为什么说mybatis是半自动的ORM框架?
用mybatis进行开发,需要手动编写SQL语句。而全自动的ORM框架,如hibernate,则不需要编写SQL语句。用hibernate开发,只需要定义好ORM映射关系,就可以直接进行CRUD操作了。由于mybatis需要手写SQL语句,所以它有较高的灵活性,可以根据需要,自由地对SQL进行定制,也因为要手写SQL,当要切换数据库时,SQL语句可能就要重写,因为不同的数据库有不同的方言(Dialect),所以mybatis的数据库无关性低。虽然mybatis需要手写SQL,但相比JDBC,它提供了输入映射和输出映射,可以很方便地进行SQL参数设置,以及结果集封装。并且还提供了关联查询和动态SQL等功能,极大地提升了开发的效率。并且它的学习成本也比hibernate低很多
思路流程:搭建环境–>导入Mybatis—>编写代码—>测试
而在编写代码时只需要通过如下几个步骤,即可用mybatis快速进行持久层的开发
1、搭建实验数据库
CREATE DATABASE `mybatis`;
USE `mybatis`;
DROP TABLE IF EXISTS `user`;
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,'偷学者1号','123456'),(2,'偷学者2号','abcdef'),(3,'偷学者3号','987654');
3、导入相关的jar 包
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.20version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiter-apiartifactId>
<version>5.8.1version>
<scope>testscope>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
4、配置log4j配置文件
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
5、配置数据源db.properties文件
这个要根据自己数据库所在的IP地址与密码
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://192.168.10.104:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf8
db.user=root
db.password=12345678
6、编写Mybatis的核心全局配置文件
<configuration>
<properties resource="db.properties">properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.password}"/>
dataSource>
environment>
environments>
configuration>
7、配置MybatisUtils工具类,来加载全局配置文件和生成SqlSessionFactory
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
try{
String resource ="mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
8、创建User实体类
这里为例防止代码冗余,我使用了Lombok插件,不会的可以去搜索如何使用,非常方便。
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private int id;
private String name;
private String pwd;
}
9、编写映射接口:
import com.zjw.bean.User;
import java.util.List;
public interface UserMapper {
List<User> selectUser();
}
10、编写对应的mapper映射文件
<mapper namespace="com.zjw.Dao.UserMapper">
<select id="selectUser" resultType="com.zjw.Dao.User">
select * from user
select>
mapper>
11、编写完mapper映射文件后去全局配置文件中去注册
<mappers>
<mapper resource="com/zjw/Dao/UserMapper.xml"/>
mappers>
12、编写测试类
public class MyTest {
@Test
public void selectUser() {
SqlSession session = MybatisUtils.getSession();
//方法一:
List<User> users = session.selectList("com.zjw.Dao.UserMapper.selectUser");
//方法二:
// UserMapper mapper = session.getMapper(UserMapper.class);
for (User user: users){
System.out.println(user);
}
session.close();
}
}
13、启动测试类,出现结果:
不过根据整个简单的项目代码来看,我们仅仅为了完成一个select操作,好像创建了许多的XML配置文件,那么似乎与他方便的特点相反呀,但其实我们在后续的编写SQL语句就非常的轻松,因为在一个 XML 映射文件中,可以定义无数个映射语句,后面我们只需要在Mapper文件中添加定义,然后在对应的XML文件编写sQL语句就可以了。
总结:
搭建好了一个环境之后,进行SQL操作,就是重复以下几个步骤:
1、配置文件中namespace中的名称为对应Mapper接口或者Dao接口的完整包名不一致
例如Mapper的映射文件
以及全局配置文件中注册的mapper地址
2、db.properties配置的属性名字与Mybatis全局配置名字不一致
3、出现找不到mapper映射文件的错误
这样的情况出现的原因我知道的有两种情况
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
4、明明数据库中的用户名与密码均填写正确却出现连接超时的情况
可以看看自己的这个是true还是false
注意在全局配置文件中,各个标签要按照如下顺序进行配置,因为mybatis加载配置文件的源码中是按照这个顺序进行解析的
<configuration>
configuration>
各个子标签说明如下:
一般将数据源的信息单独放在一个properties文件中,然后用这个标签引入,在下面environment标签中,就可以用${}占位符快速获取数据源的信息。例如我们前面给出的mybatis-config.xml中的代码
用来开启或关闭mybatis的一些特性,比如可以用
来开启延迟加载,可以用
来开启二级缓存
在mapper.xml中需要使用parameterType
和resultType
属性来配置SQL语句的输入参数类型和输出参数类型,类必须要写上全限定名,比如一个SQL的返回值映射为User类,则resultType属性要写com.zjw.Dao.User
,这太长了,所以可以用别名来简化书写,比如我在mybatis-config.xml
中加入以下代码:
<typeAliases>
<typeAlias type="com.zjw.Pojo.User" alias="user"/>
typeAliases>
然后修改UserMapper.xml代码,从而达到代码不那么繁琐的目的:
当然,如果想要一次性给某个包下的所有类设置别名,可以用如下的方式
<typeAliases>
<package name="com.zjw.bean"/>
typeAliases>
如此,指定包下的所有类,都会以简单类名的小写形式,作为它的别名。
(不经常用)
用于处理Java类型和Jdbc类型之间的转换,mybatis有许多内置的TypeHandler,比如StringTypeHandler,会处理Java类型String和Jdbc类型CHAR和VARCHAR。这个标签用的不多
(不经常用)
mybatis会根据resultType或resultMap的属性来将查询得到的结果封装成对应的Java类,它有一个默认的DefaultObjectFactory,用于创建对象实例,这个标签用的也不多
可以用来配置mybatis的插件,比如在开发中经常需要对查询结果进行分页,就需要用到pageHelper分页插件,这些插件就是通过这个标签进行配置的。在mybatis底层,运用了责任链模式+动态代理去实现插件的功能。
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
plugin>
plugins>
用来配置数据源
用来配置mapper.xml映射文件,这些xml文件里都是SQL语句。而在实际工作中,一般我们会将一张表的SQL操作封装在一个mapper.xml中 ,可能有许多张表需要操作,那么我们是不是要在
标签下写多个
标签呢?其实不用,还有第三种加载mapper的方法,使用
标签
<mappers>
<package name="com.zjw.Dao"/>
mappers>
这样就会自动加载com.zjw.Dao包下的所有mapper,这种方式需要将mapper接口文件和mapper.xml文件都放在com.zjw.Daor包下,且接口文件和xml文件的文件名要一致。
三种加载mapper的方式总结
<mappers>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
mappers>
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
mappers>
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
mappers>
mapper接口和mapper.xml之间需要遵循一定规则,才能成功的让mybatis将mapper接口和mapper.xml绑定起来
理解我们目前已经讨论过的不同作用域和生命周期类是至关重要的,因为错误的使用会导致非常严重的并发问题。
我们可以先画一个流程图,分析一下Mybatis的执行过程!
作用域理解