MyBatis
这是小弟上黑马的MyBatis的课总结的笔记,需要的兄弟姐妹们可以拿去,不到两天就可以直接上手啦。
MyBatis开发手册中文官网:https://mybatis.org/mybatis-3/zh/getting-started.html
什么是MyBatis?
MyBatis是一款持久层框架,用于简化JDBC开发
持久层和框架
JavaEE三层架构:表现层,业务层,持久层
表现层:页面展示
业务层:逻辑处理
持久层:负责数据持久化,将数据保存到数据库的一层代码
框架:一个半成品软件,是一套可以重用的、通用的软件基础代码模型,在其基础上构建软件编写更高效、规范、通用、可扩展
JDBC缺点与MyBatis的简化
JDBC缺点
1.硬编码
(1)注册驱动
(2)SQL语句
2.操作繁琐
(1)手动设置参数
(2)手动封装结果集
MyBatis的简化
硬编码-----》 使用配置文件
操作繁琐-----》 自动完成
MyBatis快速入门
1、创建user表,添加数据
2、创建模块,导入坐标
3、编写MyBatis核心配置文件-----》替换连接信息,解决硬编码问题
4、编写SQL映射文件-----》统一管理sql语句解决硬编码问题
5、编码:
(1)定义pojo类
(2)加载核心配置文件,获取SqlSessionFactory对象
(3)获取SqlSession对象,执行SQL语句
(4)释放资源
注意:logback.xml、mybatis-config.xml、xxxMapper.xml需要放在resources文件夹下面
导入坐标
写在pom.xml文件里
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!--junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<!--slf4j日志api-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.5.6</version>
</dependency>
<!--logback-classic依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.5</version>
</dependency>
<!--logback-core依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.4.5</version>
</dependency>
</dependencies>
logback配置文件
打印日志时需要,不需要日志可以不用
文件名:logback.xml
<configuration>
<appendername="STDOUT"class="ch.qos.logback.core.ConsoleAppender">
<!--encodersare bydefaultassignedthetype
ch.qos.logback.classic.encoder.PatternLayoutEncoder-->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level%logger{36} -%msg%n</pattern>
</encoder>
</appender>
<rootlevel="debug">
<appender-refref="STDOUT"/>
</root>
</configuration>
MyBatis核心配置文件
文件名:mybatis-config.xml(一般都为这个)
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEconfiguration
PUBLIC"-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environmentsdefault="development">
<environmentid="development">
<transactionManagertype="JDBC"/>
<dataSourcetype="POOLED">
<!--数据库连接信息-->
<propertyname="driver"value="com.mysql.jdbc.Driver"/>
<propertyname="url"value="jdbc:mysql:///mybatis?useSSL=false"/>
<propertyname="username"value="root"/>
<propertyname="password"value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载SQL映射文件-->
<mapperresource="UserMapper.xml"/>
</mappers>
</configuration>
SQL映射文件
文件名:xxxMapper.xml,xxx根据结果集封装到的pojo而定,如这里的是UserMapper.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEmapper
PUBLIC"-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace:名称空间
-->
<mappernamespace="test">
<selectid="selectAll"resultType="com.pojo.User">
select*fromuser;
</select>
</mapper>
编码
publicclassMyBatisDemo {
publicstaticvoidmain(String[] args) throwsIOException {
//1.加载mybatis的核心配置文件,获取SqlSessionFactory
Stringresource="mybatis-config.xml";
InputStreaminputStream=Resources.getResourceAsStream(resource);
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);
//2、获取对象,用它来执行sql
SqlSessionsqlSession=sqlSessionFactory.openSession();
//3、执行sql
List<Object>users=sqlSession.selectList("test.selectAll");
System.out.println(users);
//4、释放资源
sqlSession.close();
}
}
Mapper代理开发
1、定义与sql映射文件同名的Mapper接口,并将Mapper接口和SQL映射文件放置在同一目录下
(在resources目录下建mapper目录,要和mapper接口所在目录同名,即com.mapper,但是在resources目录下建时,要为com/mapper,否者编译后会文件名为一长串的com.mapper,而非mapper)
2、设置sql映射文件的namespace属性为Mapper接口全限定名
<!--
namespace:名称空间
-->
<mappernamespace="com.mapper.UserMapper">
<selectid="selectAll"resultType="com.pojo.User">
select*
fromuser;
</select>
</mapper>
3、在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
publicinterfaceUserMapper {
List<User>selectAll();
}
4、编码:
(1)通过 SqlSession 的 getMapper 方法获取 Mapper接口的代理对象
(2)调用对应方法完成sql的执行
//3、执行sql
//List<Object> users = sqlSession.selectList("test.selectAll");
//3.1 获取UserMapper接口的代理对象
UserMapperuserMapper=sqlSession.getMapper(UserMapper.class);
List<User>users=userMapper.selectAll();
细节:若Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载
<mappers>
<!--加载SQL映射文件-->
<!--<mapper resource="com/mapper/UserMapper.xml"/>-->
<!--Mapper代理方式-->
<package name="com.mapper"/>
</mappers>
Mapper核心配置文件
![](https://i-blog.csdnimg.cn/blog_migrate/0e5b17cddae6d56ac777c43022aaa0d4.png)
设置各个标签时,需要遵守前后循序(如上图)
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--别名,简化xxxMapper.xml,使用包扫描技术,默认为pojo类名的小写-->
<typeAliases>
<package name="com.pojo"/>
</typeAliases>
<!--
environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment,如开发时的数据库环境,测试时的数据库环境
-->
<environments default="development">
<environment id="development">
<!--事务管理,将来会给spring接管-->
<transactionManager type="JDBC"/>
<!--数据库连接池配置,将来会给spring接管-->
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载SQL映射文件-->
<!--<mapper resource="com/mapper/UserMapper.xml"/>-->
<!--Mapper代理方式-->
<package name="com.mapper"/>
</mappers>
</configuration>
使用类型别名后,xxxMapper.xml文件如下:
<mapper namespace="com.mapper.UserMapper">
<!-- <select id="selectAll" resultType="com.pojo.User">-->
<!-- select *-->
<!-- from user;-->
<!-- </select>-->
<!--使用别名-->
<select id="selectAll" resultType="user">
select *
from user;
</select>
</mapper>
配置文件完成增删改查
前置准备
1. 建好brand数据库表
2. 在pojo包下建好Brand类
3. 建brandMapper接口
4. 建brandMapper.xml
5. 在test包下,建立测试类
6. 安装mybatisX插件
查询
查询所有数据
1.编写接口方法:Mapper接口
参数:无
结果:List<brand>
2.编写SQL语句:SQL映射文件
3.执行方法,测试
brandMapper.xml文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace:名称空间
-->
<mapper namespace="com.mapper.BrandMapper">
<!--
数据库表的字段名称 和 实体类的属性名称 不一样,则不能自动封装数据
解决方法:
(1)起别名:对不一样的列名起别名,使别名和实体类属性名一样(sql语句中用as)
缺点:每次查询都得定义一次
解决:sql片段
缺点:不灵活
(2)resultMap:
1.定义<resultMap>标签
2.在<select>标签中,使用 resultMap 属性替换 resultType 属性
-->
<!--
id:唯一标识
type:映射的类型,支持别名
-->
<resultMap id="brandResultMap" type="brand">
<!--
id:完成主键字段的映射
column:表的列名
property:实体类的属性名
result:完成一般字段的映射
column:表的列名
property:实体类的属性名
-->
<result column="brand_name" property="brandName" />
<result column="company_name" property="companyName"/>
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *
from brand;
</select>
<!-- <!–sql片段–>-->
<!-- <sql id="brand_column">-->
<!-- id,brand_name as branName,company_name as companyName,ordered,description,status-->
<!-- </sql>-->
<!-- <!–使用sql片段–>-->
<!-- <select id="selectAll" resultType="brand">-->
<!-- select -->
<!-- <include refid="brand_column"/>-->
<!-- from brand;-->
<!-- </select>-->
<!-- <!–使用别名–>-->
<!-- <select id="selectAll" resultType="brand">-->
<!-- select *-->
<!-- from brand;-->
<!-- </select>-->
</mapper>
查询单行数据
1.编写接口方法:Mapper接口
参数:id
结果:Brand
2.编写SQL语句:SQL映射文件
3.执行方法,测试
brandMapper.xml文件如下:
<!--
*参数占位符:
1. #{}:会将其替换成 ? :防止SQL注入
2. ${}:拼sql,会存在SQL注入问题
3. 使用时机:(一般都用 #{} )
* 参数传递时:#{}
* 表名或者列名不确定时:${} 会存在SQL注入问题
* 参数类型:parameterType 可以省略
* 特殊字符处理:
1.转义字符:如 < 的转义字符为 <
2.CDATA区:(该区内当做纯文本处理)
<![CDATA[
]]>
-->
<select id="selectById" resultMap="brandResultMap">
select *
from brand
where id = #{id};
</select>
条件查询
多条件查询
1.编写接口方法:Mapper接口
参数:所有查询条件
结果:List<Brand>
2.编写SQL语句:SQL映射文件
3.执行方法,测试
接口方法:
/*
条件查询:
参数接收:
1. 散装参数:若方法中有多个参数,需要使用@Param("SQL参数占位符名称")
2. 对象参数:对象属性名称要和参数占位符名称一致
3. map集合参数:
*/
List<Brand> selectByCondition(@Param("status")int status,@Param("companyName")String companyName,@Param("brandName")String brandName);
List<Brand> selectByCondition02(Brand brand);
List<Brand> selectByCondition03(Map map);
对应SQL映射文件主要代码:
<select id="selectByCondition" resultMap="brandResultMap">
select *
from brand
where
status = #{status}
and company_name like #{companyName}
and brand_name like #{brandName}
</select>
<select id="selectByCondition02" resultMap="brandResultMap">
select *
from brand
where
status = #{status}
and company_name like #{companyName}
and brand_name like #{brandName}
</select>
<select id="selectByCondition03" resultMap="brandResultMap">
select *
from brand
where
status = #{status}
and company_name like #{companyName}
and brand_name like #{brandName}
</select>
对应测试方法:
@Test
public void testSelectByCondition() throws IOException {
int status = 1;
String companyName = "葡萄";
String brandName = "葡萄";
//处理参数
companyName = "%"+companyName+"%";
brandName = "%"+brandName+"%";
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
Map map = new HashMap();
map.put("status",status);
map.put("companyName",companyName);
map.put("brandName",brandName);
//1.加载mybatis的核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.获取Mapper接口代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4.执行方法
// List<Brand> brandList = brandMapper.selectByCondition(status, companyName, brandName);
// List<Brand> brandList = brandMapper.selectByCondition02(brand);
List<Brand> brandList = brandMapper.selectByCondition03(map);
System.out.println(brandList);
//5.释放资源
sqlSession.close();
}
多条件动态条件查询
上面写法有缺陷,如果条件为空,则查不出正确的信息,故需要使用动态sql,实现动态条件查询
对应SQL映射文件主要代码:
<!--
动态条件查询:
* if: 可用来判断参数是否有值
*:test:条件判断
* 问题:当不使用第一项的查询条件时,SQL语法错误
* 解决:
* 在where后加恒等式(如:1=1),再在第一个查询条件加上and
* 用<where>标签替换where关键字
-->
<select id="selectByCondition03" resultMap="brandResultMap">
select *
from brand
where
<if test="status != null">
status = #{status}
</if>
<if test="companyName != null and companyName !=''">
and company_name like #{companyName}
</if>
<if test="brandName != null and brandName !=''">
and brand_name like #{brandName}
</if>
</select>
单条件动态条件查询:
对应SQL映射文件主要代码:
<select id="selectByConditionSingle" resultMap="brandResultMap">
select *
from brand
where
<choose><!--相当于switch-->
<when test="status != null"><!--相当于case-->
status = #{status}
</when>
<when test="companyName != null and companyName !=''"><!--相当于switch-->
company_name like #{companyName}
</when>
<when test="brandName != null and brandName !=''"><!--相当于switch-->
brand_name like #{brandName}
</when>
<otherwise><!--相当于default,也可以不用这段,直接用<where>标签包裹when,效果一样-->
1=1
</otherwise>
</choose>
</select>
添加
1.编写接口方法:Mapper接口
参数:除id外的所有数据
结果:void 或 int
2.编写SQL语句:SQL映射文件
3.执行方法,测试
对应部分SQL映射文件代码:
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into brand (brand_name,company_name,ordered,description,status)
values (#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>
MyBatis事务管理:
openSession():默认开启事务,进行增删改操作后需要使用sqlSession.commit();手动提交事务
openSession(true):可以设置为自动提交事务(或关闭事务)
主键返回
添加数据成功后,获取插入数据库数据的主键的值
设置:
<insert id="add" useGeneratedKeys="true" keyProperty="id">
修改
修改全部字段
1.编写接口方法:Mapper接口
参数:所有数据
结果:void或int
2.编写SQL语句:SQL映射文件
3.执行方法,测试
对应部分SQL映射文件代码:
<update id="update">
update brand
set brand_name = #{brandName},
company_name = #{companyName},
ordered = #{ordered},
description = #{description},
status = #{status}
where id = #{id};
</update>
修改部分字段
对应部分SQL映射文件代码:
单独使用<if>标签,每句后面的逗号可能会引起语法错误,故需要结合<set>标签
<update id="update01">
update brand
<set>
<if test="brandName != null and brandName != ''">
brand_name = #{brandName},
</if>
<if test="companyName != null and companyName != ''">
company_name = #{companyName},
</if>
<if test="ordered != null">
ordered = #{ordered},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="status != null">
status = #{status}
</if>
</set>
where id = #{id};
</update>
删除
单个删除
1.编写接口方法:Mapper接口
参数:id
结果:void或int
2.编写SQL语句:SQL映射文件
3.执行方法,测试
对应部分SQL映射文件代码:
<delete id="deleteById">
delete from brand
where id = #{id};
</delete>
批量删除
1.编写接口方法:Mapper接口
参数:id数组
结果:void或int
2.编写SQL语句:SQL映射文件
3.执行方法,测试
对应部分SQL映射文件代码:
<!--
mybatis会将数组参数封装为一个Map集合
* 默认:array = 数组
* 或使用@Param注解改变map集合的默认key的名称
* separator="," 表示遍历得到的值用逗号隔开
* open="(" close=") 表示以左括号开头,右括号结尾
-->
<delete id="deleteByIds">
delete from brand
where id
in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
</foreach>
;
</delete>
注解
在xxxMapper接口文件写,如:
@Select("select * from brand where id = #{id}")
Brand selectById(int id);
插入、修改、删除操作同理
但是注解只能进行简单的sql操作,一旦sql语句里面涉及到例如动态sql时,就会显得力不从心
故当要完成简单的功能,可以用注解写sql语句;但要完成较复杂的功能,则用配置文件写sql语句