MyBatis认识
Mybatis是一款orm(对象关系映射)框架,自己写sql,效率高,性能好控制
jdbc特点:
- 执行效率高,自己写sql
- 开发效率低,很多重复代码
jpa特点:
- 开发效率高,直接调用api即可完成对应crud
- 执行效率低:因为sql语句是自动生成的,性能不太好控制
Mybatis特点:
- 开发效率比jdbc高,因为消除了许多重复代码
- 执行效率比jpa高,因为是自己写sql
Mybatis的三大核心对象
SqlSessionFactoryBuilder(SqlSession工厂构建对象):该对象主要用于创建SqlSessionFactory对象 SqlSessionFactory(SqlSession工厂对象):它是一个重量级对象,在当前应用系统中应该只有一个 (线程安全的)
为什么说是一个重量级对象?
- 内部存储了mybatis核心配置xml的基本信息
- 内部有二级缓存
- 内部存储了连接池对象
所以我们不能轻易销毁该对象,它的生命周期应该随着tomcat的启动而创建,tomcat关闭而销毁
SqlSession:他是一个轻量级对象,线程不安全的
- 内部存储有连接对象
- 存储一级缓存
- 一个线程获取一个SqlSession,线程不安全的
Mybatis细节
mybatis-config.xml文件的配置顺序
configuration的子元素必须按照由上到下的顺序配置,否则MyBatis在解析XML配置文件的时候会报错
configuration 配置
--- properties 属性
--- settings 设置
--- typeAliases 类型别名
--- typeHandlers 类型处理器
--- objectFactory 对象工厂
--- plugins 插件
--- environments 环境
--- environment 环境变量
--- transactionManager 事务管理器
--- dataSource 数据源
--- databaseIdProvider 数据库厂商标识
--- mappers 映射器
引入jdbc.properties 配置数据库连接
数据库连接使用配置文件方式
jdbc.properties文件
username=root
password=123456
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///mybatis
Mybatis核心配置文件:mybatis-config.xml
<?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>
<!--引入jdbc.properties文件-->
<properties resource="jdbc.properties"/>
<!-- 配置连接数据库的环境-->
<environments default="mysql">
<!--给环境取一个别名-->
<environment id="mysql">
<!--配置事务类型:JDBC-->
<transactionManager type="JDBC"/>
<!--使用连接池对象-->
<dataSource type="POOLED">
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
</dataSource>
</environment>
</environments>
</configuration>
配置类型别名
在mybatis-config.xml里配置类型别名,之后再mapper.xml中直接使用别名
mybatis-config.xml:
<!--配置全限定名对应的别名-->
<typeAliases>
<!--给Product全限定名取了一个别名-->
<typeAlias type="cn.itsource.mybatis._01hello.domain.Product" alias="Product"/>
</typeAliases>
mapper.xml:
获取映射器
在mybatis-config.xml中配置映射器,在mapper.xml中namespace(命名空间)名必须和mapper层(dao层)对应的接口全限定名
mybatis-config.xml:
<!--配置sql映射文件-->
<mappers>
<mapper resource="cn/itsource/mybatis/_01hello/dao/impl/ProductDaoImpl.xml"/>
<mapper resource="cn/itsource/mybatis/_02mapper/mapper/EmployeeMapper.xml"/>
</mappers>
mapper.xml:
通过SqlSession对象的getMapper方法获取映射器对象
@Test
public void save() throws Exception {
//获取SqlSession
SqlSession sqlSession = MybatisUtils.openSession();
//获取映射器
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setName("李很弱231231");
employee.setSex(false);
employee.setAge(33);
employeeMapper.save(employee);
sqlSession.commit();
}
mapper.xml的sql细节
添加时拿到返回的主键
把keyColumn数据库id这列对应的值 封装到keyProperty对应的属性中
useGeneratedKeys="true":表示要返回主键idkeyColumn="id": 数据库id列keyProperty="id":实体类id属性字段
自定义映射规则
当数据库的列名和domain中的属性名不能对应的时候,我们就必须定义自定义映射规则 mybatis默认的映射规则: 数据库的列名和domain中的属性名对应,就赋值,否则不能赋值
mapper.xml:
<!--
配置自定义映射规则
id=""自定义映射规则的别名
type 最终转为指定的类型
-->
<resultMap id="productResultMap" type="Product">
<!--主键映射使用id-->
<id column="id" property="sid"/>
<!--普通属性使用result来映射-->
<result column="dir_id" property="dirId"/>
</resultMap>
<!--
resultType:返回的结果值类型
resultMap:自定义映射规则
-->
<select id="selectAll" resultMap="productResultMap">
SELECT * FROM product
</select>
动态sql语句
动态where条件,where标签
where标签的作用: 它会把第一个and换成where。其他不变
<select id="selectByQuery" parameterType="EmployeeQuery" resultType="Employee">
SELECT <include refid="columnSql"/> FROM t_employee
<where>
<if test="name!=null and name!=''">
AND name LIKE CONCAT("%",#{name},"%")
</if>
<if test="sex!=null">
AND sex=#{sex}
</if>
</where>
</select>
动态修改语句,set标签
set标签的作用:他会把第一个表达式前加set,并且去掉最后一个表达式的逗号
<update id="update">
UPDATE t_student
<set>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="age!=null">
age=#{age},
</if>
<if test="email!=null and email!=''">
email=#{email},
</if>
<if test="sex!=null">
sex=#{sex},
</if>
</set>
WHERE id=#{id}
</update>
抽取公共sql
能抽sql语句哪些部分呢?
- where条件
- sql查询的列
<sql id="columnSql">
id,name,age,sex
</sql>
<select id="selectAll" resultType="Employee">
SELECT
<include refid="columnSql"/>
FROM t_employee
</select>
<sql id="whereSql">
<where>
<if test="name!=null and name!=''">
AND name LIKE CONCAT("%",#{name},"%")
</if>
<if test="sex!=null">
AND sex=#{sex}
</if>
<if test="minAge!=null">
AND age>=#{minAge}
</if>
<if test="maxAge!=null">
<![CDATA[AND age<=#{maxAge}]]>
</if>
</where>
</sql>
<select id="selectByQuery" parameterType="EmployeeQuery" resultType="Employee">
SELECT <include refid="columnSql"/> FROM t_employee
<include refid="whereSql"/>
</select>
sql语句处理特殊符号
<![CDATA[字符串表达式]]> :会将xml中的字符串保持原样
CONCAT("%",#{name},"%"):拼接字符串
<select id="selectByQuery" parameterType="EmployeeQuery" resultType="Employee">
SELECT id,name,age,sex FROM t_employee
<where>
<if test="name!=null and name!=''">
AND name LIKE CONCAT("%",#{name},"%")
</if>
<if test="maxAge!=null">
<![CDATA[AND age<=#{maxAge}]]>
</if>
</where>
</select>
批量删除
在xml中实现以下批量删除sql
DELETE FROM t_employee WHERE id in (id1,id2,id3)
使用foreach标签:该标签支持遍历数组和list集合
<!--collection="array|list"-->
<!--array方式-->
<delete id="batchDelete" parameterType="long[]">
DELETE FROM t_employee
WHERE id in
<!--
open="" 开始位置
item="x" 循环迭代给每个元素取的别名
separator="," 循环每次以指定的字符进行分割
-->
<foreach collection="array" open="(" item="x" separator="," close=")">
#{x}
</foreach>
</delete>
<!--list方式-->
<delete id="batchDelete2" parameterType="list">
DELETE FROM t_employee
WHERE id in
<foreach collection="list" open="(" item="x" separator="," close=")">
#{x.id}
</foreach>
</delete>
批量添加
在xml中实现以下批量添加sql
INSERT INTO t_employee(name, age, sex)
VALUES (name1,age1,sex1),(name2,age2,sex2)
mapper.xml
<insert id="batchSave" parameterType="list">
INSERT INTO t_employee(name, age, sex) VALUES
<foreach collection="list" item="x" separator=",">
(#{x.name},#{x.age},#{x.sex})
</foreach>
</insert>