MyBatis介绍
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
框架优点
- 提高开发效率
- 统一的编码规则,利于团队管理
- 灵活配置的应用,拥有更好的维护性
SSM开发框架
MyBatis开发流程
单元测试与JUnit 4
单元测试:
- 单元测试是指对软件中的最小可测试单元进行检查和验证
- 测试用例是指编写一段代码对已有功能(方法)进行校验
- JUnit 4是Java中最著名的单元测试工具,主流IDE内置支持
JUnit 4使用方法:
- 引入JUnit Jar包或增加Maven依赖
- 编写测试用例验证目标方法是否正确运行
- 在测试用例上增加@Test注解开始单元测试
MyBatis基本使用
MyBatis配置
- MyBatis采用XML格式配置数据库环境信息
- MyBaits环境配置标签
- environment包含数据库驱动、URL、用户名与密码
(47条消息) Mybatis连接池介绍与分类 Mybatis使用POOLED UNPOOLED配置连接池的原理分析_韦恩少爷的背的博客-CSDN博客_pooled
SqlSessionFactory
- SqlSessionFactory是MyBatis的核心对象
- 用于初始化MyBatis,创建SqlSession对象
- 保证SqlSessionFactory在应用中全局唯一
//利用Reader加载classpath下的mybatis-config.xml核心文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//初始化SqlSessionFactory对象,同时解析mybatis-config.xml文件
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
System.out.println("sqlSessionFactory加载成功");
SqlSession sqlSession = null;
try {
//创建SqlSession对象,SqlSession是JDBC的扩展类,用于数据库交互
sqlSession = sqlSessionFactory.openSession();
//创建数据库连接(测试用)
Connection connection = sqlSession.getConnection();
System.out.println(connection);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
// 如果type="POOLED",代表使用连接池,close则是将连接回收至连接池中
// 如果type="UNPOOLED",代表直连,close则会调用Connection.close()方法关闭连接
sqlSession.close();
}
}
MyBatisUtils工具类
代码语言:javascript复制/**
* MyBatisUtils工具类,创建全局唯一的SqlSessionFactory对象
*/
public class MyBatisUtils {
// 利用static(静态)属于类不属于对象,且全局唯一
private static SqlSessionFactory sqlSessionFactory = null;
//利用静态块在初始化类时实例化SqlSessionFactory
static {
try {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
//初始化错误时,通同抛出异常 ExceptionInInitializerError 通知调用者
throw new ExceptionInInitializerError(e);
}
}
/**
* openSession 创建一个新的SqlSession对象
*
* @return SqlSession对象
*/
public static SqlSession openSession() {
return sqlSessionFactory.openSession();
}
/**
* 释放一个SqlSession对象
*
* @param session 准备释放SqlSession对象
*/
public static void closeSession(SqlSession session) {
if (session != null) {
session.close();
}
}
}
MyBatis数据查询
SQL传参
- 但参数传递:使用parameterType指定参数的数据类型即可,SQL中#{value}提取参数
public void testSelectById() {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById", 1520);
System.out.println(goods.getTitle());
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
- 多参数传递:使用parameterType指定Map接口,SQL中#{Key}提取参数
public void testSelectByPriceRange() {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Map param = new HashMap();
param.put("min", 100);
param.put("max", 500);
param.put("limt", 10);
List<Goods> list = sqlSession.selectList("selectByPriceRange", param);
for (Goods g : list) {
System.out.println(g.getTitle() " 价格:" g.getCurrentPrice());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
多表关联查询
利用LinkedHashMap保存多表关联结果
MyBatis会将每一条记录包装为LinkedHashMap对象
key是字段名value是字段对应的值,字段类型根据表结构进行自动判断优点:易于扩展,易于使用
缺点:太过灵活,无法进行编译时检查
代码语言:javascript复制<!--利用LinkedHashMap保存多表关联结果
MyBatis会将每一条记录包装为LinkedHashMap对象
key是字段名value是字段对应的值,字段类型根据表结构进行自动判断
优点:易于扩展,易于使用
缺点:太过灵活,无法进行编译时检查-->
<select id="selectGoodsMap" resultType="java.util.LinkedHashMap">
select g.*, c.category_name
from t_goods g,
t_category c
where g.category_id = c.category_id;
</select>
ResultMap结果映射
- ResultMap可以将查询结果映射为复杂类型的Java对象
- ResultMap适用于Java对象保存多表关联结果
- ResultMap支持对象关联查询等高级特性
<!--结果映射,id:一般为rm 单词-->
<resultMap id="rmGoods" type="pers.hua.mybatis.dto.GoodsDTO">
<!--设置主键字段与属性映射-->
<id property="goods.goodsId" column="goods_id"></id>
<!--设置非主键字段与属性映射-->
<result property="goods.title" column="title"></result>
<result property="goods.originalCost" column="original_cost"></result>
<result property="goods.currentPrice" column="current_price"></result>
<result property="goods.discount" column="discount"></result>
<result property="goods.isFreeDelivery" column="is_free_delivery"></result>
<result property="goods.categoryId" column="category_id"></result>
<result property="categoryName" column="category_name"/>
</resultMap>
<select id="selectGoodsDTO" resultMap="rmGoods">
select g.*, c.category_name
from t_goods g,
t_category c
where g.category_id = c.category_id;
</select>
MyBatis的数据插入、修改与删除
插入数据
代码语言:javascript复制<!--1. parameterType:要指向实体类,
2. 同时在传入的时候要新增传入的数据
3. 对于主键自动生成的情况,获取每次新产生数据ID号(selectKey)-->
<insert id="insert" parameterType="pers.hua.mybatis.entity.Goods">
INSERT INTO t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery,
category_id)
VALUES (#{title}, #{subTitle}, #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryId});
<selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
select last_insert_id();
</selectKey>
</insert>
selectKey和useGeneratedKeys的区别
selectKey标签用法
useGeneratedKeys属性用法
二者区别
- selectKey标签需要明确编写获取最新主键的SQL语句
- useGeneratedKeys属性会自动根据驱动生成对应SQL语句
应用场景
- selectKey适合所有的关系型数据库
- useGeneratedkeys只支持"自增主键"类型的数据库
更新数据
删除数据
Sql注入攻击
MyBatis两种传值方式
- ${}文本替换,未经任何处理对SQL文本替换
- #{}预编译传值,使用预编译传值可以预防SQL注入