本文将系统的介绍Mybatis,从Mybatis是什么,到如何使用Mybatis,再到Mybatis的底层实现原理,最后到Mybatis的常见面试题都会介绍到,希望能够为初学Mybatis的伙伴们提供到一点点的帮助。
MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁 移到了Google Code。随着开发团队转投Google Code旗下, iBatis3.x正式更名为MyBatis。代码于 2013年11月迁移到Github。
iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。 iBatis提供的持久层框架 包括SQL Maps和Data Access Objects(DAO)。
Mybatis是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性
ORM是什么?
ORM:Object Relation Mapping,对象关系映射。Object就是指Java中的对象,Relation指的是数据库中的关系模型,对象关系映射,指的就是在Java对象和数据库的关系模型之间建立一种对应关系,比如用一个Java的Student类,去对应数据库中的一张student表,类中的属性和表中的列一一对应。Student类就对应student表,一个Student对象就对应student表中的一行数据。
为什么说Mybatis是半自动的ORM持久层框架,而不是全自动呢?
Mybatis的开发过程中需要程序员手写对应的SQL语句,这种需要手写SQL语句的就叫做半自动的ORM持久层框架,而不需要手写SQL语句的框架就是全自动的。
这样半自动的ORM持久层框架虽然提高了对程序员掌握SQL的要求,但同样也使代码变得更加灵活,要知道不同的SQL需要调用的磁盘是不同的,全自动的框架无法调整对磁盘的要求,如果程序需要进一步优化,Mybatis就可以通过调整SQL语句降低磁盘的使用率。
实现Mybatis的开发,要先了解一下Mybatis的层次,Mybatis的开发模型参考MVC模型,在开发中分为了两层,pojo、dao。
pojo是数据库实体类,对应数据库中的数据。
dao是调用数据库信息的层,用于实现对数据库的增删查改,通常与xml文件配合使用。
除了上述两层外,还要使用配置文件配置数据库连接。
SSM项目中导入Mybatis
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.23version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.6version>
dependency>
SpringBoot项目中导入Mybatis
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.3.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
全局配置文件要配置数据源连接、加载全局的SQL语句文件。
数据源properties文件
application.driver=com.mysql.cj.jdbc.Driver
application.url=jdbc:mysql://localhost:3306/acc?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true
application.username=root
application.password=root
全局xml配置文件(mybatis-config.xml)
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="application.properties">properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${application.driver}"/>
<property name="url" value="${application.url}"/>
<property name="username" value="${application.username}"/>
<property name="password" value="${application.password}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/lmz/mapper/UserMapper.xml"/>
mappers>
configuration>
实体类的数据类型必须与MySQL的数据类型一致,最好使用包装类。
其中MySQL中decimal类型对应Java实体类中的BigDecimal类型。
package com.lmz.pojo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.math.BigDecimal;
@Getter
@Setter
@ToString
public class User {
public Integer userId ;
public BigDecimal userNum ;
public String userName ;
public String password ;
public User(){}
public User(BigDecimal userNum , String userName , String password ) {
this.userNum = userNum ;
this.userName = userName ;
this.password = password ;
}
}
采用接口的形式进行定义,映射到xml文件中的sql语句
package com.lmz.mapper;
import com.lmz.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import java.math.BigDecimal;
import java.util.List;
/**
* User实体的映射类
*/
public interface UserMapper {
/**
* 查寻全部
*/
List<User> selectAll();
/**
* 增加
*/
int insertUser(User user);
/**
* 删除
*/
int deleteUser(int userId);
/**
* 更新 返回值为SQL语句执行的数量
*/
int updateUser(User user);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lmz.mapper.UserMapper">
<select id="selectAll" resultType="com.lmz.pojo.User">
select * from `user`;
select>
<insert id="insertUser" parameterType="com.lmz.pojo.User">
INSERT INTO `user` (userNum,userName,password) VALUES (#{userNum},#{userName},#{password});
insert>
<delete id="deleteUser" parameterType="int">
DELETE FROM `user` WHERE userId = #{id};
delete>
mapper>
package com.lmz.util;
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;
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//使用mybatis第一步、获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//采用单例的方式,获取SQLSession
// SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
package com.lmz.mapper;
import com.lmz.pojo.User;
import com.lmz.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.List;
public class UserMapperTest {
public static SqlSession sqlSession = MybatisUtil.getSqlSession();
@Test
public void selectAll(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectAll();
System.out.println();
for(User user : users) {
System.out.println(user);
}
sqlSession.close();
}
@Test
public void insertUser(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = new User(new BigDecimal("15586531930"), "lmz测试号", "123456");
int i = mapper.insertUser(user1);
System.out.println(i);
//查看插入情况
List<User> users = mapper.selectAll();
System.out.println();
for(User user : users) {
System.out.println(user);
}
sqlSession.close();
}
@Test
public void deleteUser(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.deleteUser(4);
System.out.println(i);
//查看删除情况
List<User> users = mapper.selectAll();
System.out.println();
for(User user : users) {
System.out.println(user);
}
sqlSession.close();
}
}
MyBatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息
可以通过properties属性来实现引用配置文件
这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。
外部配置文件替换
<properties resource="application.properties">properties>
MyBatis 可以配置成适应多种环境
注意:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
配置多个环境就是在environments中包含多个environment标签,其中environments中default参数,表示的是当前使用的环境。
下面具体介绍environments的每个标签:
- environments:环境们,mybatis可以配置多种环境 ,default指定使用某种环境。可以达到快速切换环境。
- environment:配置一个具体的环境信息;id代表当前环境的唯一标识
- transactionManager:事务管理器;type:事务管理器的类型;JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory); 自定义事务管理器:实现TransactionFactory接口.type指定为全类名
- dataSource:数据源;type:数据源类型;UNPOOLED(UnpooledDataSourceFactory)|POOLED(PooledDataSourceFactory)|JNDI(JndiDataSourceFactory); 自定义数据源:实现DataSourceFactory接口,type是全类名
dataSource参数解释:
<environments default="dev_mysql">
<environment id="dev_mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${mys.driver}" />
<property name="url" value="${mys.url}" />
<property name="username" value="${mys.username}" />
<property name="password" value="${mys.password}" />
dataSource>
environment>
<environment id="dev_oracle">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${orcl.driver}" />
<property name="url" value="${orcl.url}" />
<property name="username" value="${orcl.username}" />
<property name="password" value="${orcl.password}" />
dataSource>
environment>
environments>
类型别名是为 Java 类型设置一个短的名字。 存在的意义仅在于用来减少类完全限定名的冗余。
方法一:直接命名
<typeAliases>
<typeAlias type="com.lmz.pojo.User" alias="User"/>
typeAliases>
方法二:默认别名
可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如: 扫描实体类的包,他的默认别名就是这个类的类名,首字母小写!
<typeAliases>
<package name="com.lmz.pojo"/>
typeAliases>
如果要自定义别名,可以采用@Alias注解
/**
* 将User的别名设置为thisIsUser
*/
@Alias(“thisIsUser”)
public class User {
…
}
<mappers>
<mapper resource="com/lmz/mapper/UserMapper.xml"/>
mappers>
到此,mybatis最基础的实现就已经完成了,总结一下mybatis的实现过程,首先编写全局的配置文件,也就是Java连接数据库的账号和密码,以及将xml文件注册在核心文件中,mybatis会通过读取核心文件,来查找其他配置文件的位置。
然后当mybatis调用到mapper方法的时候,会调用对应的xml文件中的sql语句,无需编写jdbc的语句,直接调用xml文件中的sql语句,将参数注入到其中,就完成了对数据库的操作。
接下来会通过分析mybatis底层实现的方式,来对其进行分析具体是如何实现连接数据库的操作的,以及是如何实现对xml文件进行读取的。
mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件中构建出SqlSessionFactory,然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的操作和事务提交,最后关闭SqlSession。
1)mybatis的启动是从读取mybatis-config.xml开始的,mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。将mybatis-config.xml转换为InputStream。
2)在解析mybatis-config.xml文件时,也会对其mapper标签进行解析,在解析mapper标签时,就解析了SQL映射文件。
3)采用SqlSessionFactoryBuilder解析mybatis-config.xml文件,根据mybatis-config.xml中内容,构建SqlSessionFactory。
4)创建会话对象。由SqlSessionFactory创建SQLSession对象,该对象包含了执行SQL语句的所有方法。
5)Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
6)MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
文章持续更新中。。。