- Mybatis是一款优秀的持久层框架,用于简化JSBC开发
- Mybatis官网:Mybatis官网
什么是持久层?
- 负责将数据保存到数据库的那一层代码
- JavaEE三层架构:表现层、业务层、持久层
JDBC缺点(关于JDBC,可见我上一篇文章JDBC编程详解以及Druid的使用)
- 硬编码
- 注册驱动,获取连接
- sql语句
- 操作繁琐
Mybati使用步骤总结
- 配置Mybtis核心配置文件(一般将其命名为 mybatis-config.xml)
- 根据核心配置文件创建 SqlSessionFactory 对象
- 通过 SqlSessionFactory 对象创建 SqlSession 对象
- 通过 SqlSession 对象操作数据库 CRUD
- 提交事务
- 释放资源
// 加载 mybatis核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession 对象, 执行 sql
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行 sql
// "名称空间.id" 是sql映射文件中sql语句的唯一标识
List<User> users = sqlSession.selectList("名称空间.id");
// 释放资源
sqlSession.close();
从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。XML 配置文件中包含了对 MyBatis系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。通过核心配置文件,我们可以替换连接信息,解决硬编码问题。这里先给出一个简单的示例:
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<typeAliases>
<package name="com.tyt.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/tyt/mapper/UserMapper.xml"/>
mappers>
configuration>
其中数据源的连接信息将其写在db.properties中,详情如下:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=false
username=root
password=****
SQL映射文件可统一管理SQL语句,解决硬编码问题。这里给出一个示例(四个基础的增删改查):
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
<insert id="add" useGeneratedKeys="true" keyColumn="id">
insert into tb_brand (companyName, brandName, ordered, description, status)
values (#{companyName}, #{brandName}, #{ordered}, #{description}, #{status});
insert>
<delete id="deleteById">
delete from tb_brand where id = #{id};
delete>
<update id="update">
update tb_brand
set
brandName = #{brandName},
companyName = #{companyName},
ordered = #{ordered},
description = #{description},
status = #{status}
where id = #{id};
update>
<select id="selectAll" resultType="Brand">
select * from tb_brand;
select>
mapper>
SQL映射文件中的sql语句有两个占位符,分别是:#{}
与${}
。
我们一般采用#{}
,#{}
在Mybatis会被解析为?
,就是JDBC中的PreparedStatement中的?
占位符,说明它也有预编译的功能。
* 参数占位符:
1: #{}: 将其替换为'?' , 防止 sql 注入
2: ${}: 拼 sql, 存在 sql 注入
3. 使用时机:
* 参数传递时: #{}
* 表名或列名不固定时: ${}
* 参数类型: parameterType 可省略
* 特殊字符处理
1、转义字符:
2. CDATA: <1[CDATA[ 符号 ]]>
当数据库表列名与实体类属性名不一致时,不能自动封装数据。例如,在数据库中,使用下划线命名方式;在实体类中,使用驼峰命名。在此,提供了三种解决方案,其中第三个使用reultMap最为广泛使用。
我这里有一个表tb_brand并定义了实体类Brand,可以发现,在数据库中使用的下划线命名,在实体类中使用的驼峰命名。
目的
- 定义与SQL映射文件同名的Mapper接口,并将其Mapper接口和SQL映射文件放置在同一目录
- 设置SQL映射文件的namespace属性为Mapper接口限定全名
- 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
- 编码
① 通过SqlSession的getMapper方法获取Mapper接口的代理对象
② 调用对应方法完成sql的执行
注:如果Mapper接口名称与SQL映射文件名称相同,并在同一目录,则可使用包扫描的方式简化SQL映射文件的加载
①SQL映射文件与SQL映射文件同名的Mapper接口
② 设置SQL映射文件的namespace属性为Mapper接口限定全名
如果不习惯用xml配置文件,则可以考虑使用注解的开发方式。注解的开发方式,会将sql语句写入代码,缺点是后续可维护性与拓展性不强(若想修改sql语句,需要更改代码,重新打包部署,但使用xml方式,只需修改xml文件,并用新的文件替代原xml文件即可)
- 查询:@Select
- 添加:@Insert
- 修改:@Update
- 删除:@Delete
提示:
- 注解完成简单功能
- 配置文件完成复杂功能
Mybatis中SQL语句有3种方式可以设置参数:
①散装参数:需要使用@Param(“SQL中的参数占位符名称”)
②实体类封装参数:需要保证SQL中的参数名与实体类的属性名对应上
③Map集合需要保证SQL中的参数名与Map集合中的键的名称对应上
SQL语句随着用户输入或外部条件的变化而变化,我们称为动态SQL。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
① if
if 标签通常用于 WHERE 语句、UPDATE语句、INSERT语句,通过判断参数值来决定是否使用某个查询条件、判断是否更新或插入某一字段的值。
② choose
有时候需求并不需要应用所有条件,而只是想从多选型中选择一个。Mybatis提供了标签(类似Java的switch),按顺序判断
标签(类似Java的case)中条件,若条件都不满足,执行
标签(类似Java的default)的语句。
③trim
④foreach标签
标签主要用于构建
in
条件,可在sql语句中对集合进行迭代。也可用于批量删除、添加等操作中。
属性介绍
- collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。
- item :表示在迭代过程中每一个元素的别名
- separator :分隔符,表示迭代时每个元素之间以什么分隔
- open :前缀
- close :后缀
- index :表示在迭代过程中每次迭代到的位置(下标)
在某些需求中,需要在数据添加成功后,获取插入数据库数据的主键的值。
只需要在标签中添加两个数据即可。
useGeneratedKeys="true" keyProperty="主键列名"
SqlSessionFactory
代码优化 // 加载 mybatis核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- 缺点及解决:
- 代码重复:
使用工具类
- SqlSessionFactory工厂只创建一次,不能重复创建:
使用静态代码块
使用方法:
①定义获取SqlSessionFactory工具类
public class SqlSessionFactoryUtils {
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 SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
②获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
①引入maven依赖
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.2.0version>
dependency>
②加入plugin配置
在mybatis核心配置文件中(mybatis-config.xml)配置PageHelper插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
③代码
<select id="selectByPage" resultType="Brand" >
select * from tb_brand
select>
// 加载 mybatis核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession 对象, 执行 sql
SqlSession sqlSession = sqlSessionFactory.openSession();
// 设置分页相关参数 当前页 + 每页显示的条数
PageHelper.startPage(1, 2);
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
List<Brand> brands = brandMapper.selectByPage();
System.out.println(brands);
sqlSession.close();