一、MyBatis简介
一、MyBatis介绍
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
二、功能流程
二、快速搭建
sql语句:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for customers
-- ----------------------------
DROP TABLE IF EXISTS `customers`;
CREATE TABLE `customers` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(15) CHARACTER SET gb2312 COLLATE gb2312_chinese_ci NULL DEFAULT NULL,
`email` varchar(20) CHARACTER SET gb2312 COLLATE gb2312_chinese_ci NULL DEFAULT NULL,
`birth` date NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = gb2312 COLLATE = gb2312_chinese_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of customers
-- ----------------------------
INSERT INTO `customers` VALUES (1, '汪峰', 'wf@126.com', '2010-02-02');
INSERT INTO `customers` VALUES (2, '王菲', 'wangf@163.com', '1988-12-26');
INSERT INTO `customers` VALUES (3, '林志玲', 'linzl@gmail.com', '1984-06-12');
INSERT INTO `customers` VALUES (4, '汤唯', 'tangw@sina.com', '1986-06-13');
INSERT INTO `customers` VALUES (5, '成龙', 'Jackey@gmai.com', '1955-07-14');
INSERT INTO `customers` VALUES (6, '迪丽热巴', 'reba@163.com', '1983-05-17');
INSERT INTO `customers` VALUES (7, '刘亦菲', 'liuyifei@qq.com', '1991-11-14');
INSERT INTO `customers` VALUES (8, '陈道明', 'bdf@126.com', '2014-01-17');
INSERT INTO `customers` VALUES (10, '周杰伦', 'zhoujl@sina.com', '1979-11-15');
INSERT INTO `customers` VALUES (12, '黎明', 'LiM@126.com', '1998-09-08');
INSERT INTO `customers` VALUES (13, '张学友', 'zhangxy@126.com', '1998-12-21');
INSERT INTO `customers` VALUES (16, '朱茵', 'zhuyin@126.com', '2014-01-16');
INSERT INTO `customers` VALUES (18, '贝多芬', 'beidf@126.com', '2014-01-17');
INSERT INTO `customers` VALUES (22, '聪宝宝', '13231231@qq.com', '1998-12-17');
SET FOREIGN_KEY_CHECKS = 1;
1、创建maven工程
2、添加依赖
<dependencies>
<!--mysql8 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!--MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
注意mysql与驱动对应的版本关系
3、在resources中创建sqlMapConfig配置文件
sqlMapConfig:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="mysqlConfig.properties">
</properties>
<typeAliases>
<package name="com.bihai.pojo"></package>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="driver" value="${driver}"></property>
<property name="url" value="${url}"></property>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/bihai/mapper/ICustomersMapper.xml"></mapper>
</mappers>
</configuration>
具体标签含义功能后序介绍。
mysqlConfig.properties:
username=root
password=19981217
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/myemployees?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&userSSL=false
注意: 对于mysql 8版本,需要在url后面加上时区信息,同时driver路径也发生了一些改变。
4、创建接口与实体类
接口:
com.bihai.mapper.ICustomersMapper
public interface ICustomersMapper {
Customers selectById(Integer id);
}
实体类:
com.bihai.pojo.Customers
public class Customers {
private Integer id;
private String name;
private String email;
private String birth;
public Customers() {
}
public Customers(Integer id, String name, String email, String birth) {
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirth() {
return birth;
}
public void setBirth(String birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Customers{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", birth='" + birth + '\'' +
'}';
}
}
5、创建映射配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bihai.mapper.ICustomersMapper">
<select id="selectById" resultType="customers">
select * from customers where id = ${value};
</select>
</mapper>
6、测试
public class MyBatisTest {
private static SqlSessionFactory factory;
static {
//1.读取配置文件
InputStream resourceAsStream = null;
try {
resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
//2.创建sqlSessionFactory工厂,创建者模式(对象的创建细节隐藏)
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
factory = sqlSessionFactoryBuilder.build(resourceAsStream);
}
@Test
public void test2(){
try(SqlSession sqlSession = factory.openSession()){
ICustomersMapper mapper = sqlSession.getMapper(ICustomersMapper.class);
Customers customers = mapper.selectById(1);
System.out.println(customers);
}
}
@Test
public void test3(){
try(SqlSession sqlSession = factory.openSession()) {
Object customer = sqlSession.selectOne("com.bihai.mapper.ICustomersMapper.selectById", 1);
System.out.println(customer);
}
}
}
三、作用域与生命周期
注意:
依赖注入框架(MyBatis-Spring)可以创建线程安全的、基于事务的 SqlSession 和映射器,并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。
一、作用域及其生命周期
1、SqlSessionFactoryBuilder
生命周期:
一旦创建了 SqlSessionFactory,就不再需要它了。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
作用域:
因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域
2、SqlSessionFactory
生命周期:
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
作用域:
使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
3、SqlSession
生命周期:
绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。
例如:
try (SqlSession session = sqlSessionFactory.openSession()) {
// 你的应用逻辑代码
}
作用域:
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
四、参数
有时根据需要传入各个类型的参数,比如:复合类型,简单类型,map集合等,但总体来说分为两类:单参数,多参数,同时可以配合OGNL表达式。
一、OGNL表达式
它是 apache 提供的一种表达式语言,全称是: Object Graphic Navigation Language 对象图导航语言 。
它是按照一定的语法格式来获取数据的。 语法格式就是使用 #{对象.对象}的方式。
#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。
但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user. 而直接写 username
二、单参数
接口定义:
Customers selectById(Integer id);
List<Customers> selectByMap(HashMap<String,Object> map);
List<Customers> selectByQuery(Customers customers);
1、简单数据类型
<select id="selectById" resultType="customers">
select * from customers where id = #{value};
</select>
2、复合数据类型
<select id="selectByMap" resultType="customers">
select * from customers where name = #{name} and email = #{email}
</select>
3、Map集合
<select id="selectByQuery" resultType="customers">
select * from customers where name = #{name} and email = #{email}
</select>
注意: 对于单参数,Mybatis会自动识别类型,因此可以不设置parameterType属性,但为了可观性可以写上。
三、多参数
接口定义:
List<Customers> selectByMultiParam(String id,String name);
List<Customers> selectByMultiParam1(int id,Map<String,Object> map);
对于多参数的情况,可以使用@Param来解决,也可以利用其出现的顺序来解决
1、简单多参数
使用@Param:
List<Customers> selectByMultiParam(@Param(value = "id") String id,@Param(value = "name") String name);
<select id="selectByMultiParam" resultType="customers">
select * from customers where id = #{id} and name = #{name}
</select>
使用其出现的顺序:
使用argx,x从0开始表示第一个参数
<select id="selectByMultiParam" resultType="customers">
select * from customers where id = #{arg0} and name = #{arg1}
</select>
or
使用paramx,x从1开始表示第一个参数
<select id="selectByMultiParam" resultType="customers">
select * from customers where id = #{param1} and name = #{param2}
</select>
2、复合多参数
使用@Param:
List<Customers> selectByMultiParam1(@Param(value = "id") int id, @Param(value = "map") Map<String,Object> map);
<select id="selectByMultiParam1" resultType="customers" >
select * from customers where id = #{id} and name = #{map.name}
</select>
使用其出现的顺序:
<select id="selectByMultiParam1" resultType="customers" >
select * from customers where id = #{arg0} and name = #{arg1.name}
</select>