Mybatis是持久层框架,用于简化JDBC的开发。持久层就是Dao层
Mabatis入门
1.准备springBoot工程,引入相关依赖
2.配置下面的数据库连接信息,我们将他配置在application.properties配置文件中
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.username=root
spring.datasource.password=1234
- 驱动
- URL:开头的jdbc:mysql://是固定的协议部分,localhost:3306是地址和端口号,/mybatis是数据库名字。
- 用户名
- 密码
3.编写SQL语句(注解/XML)
首先要定义一个持久层的接口,上面加上@Mapper注解标识当前就是Mybatis当中的持久层接口,也就是之前定义的dao层的接口。 在运行时会自动生成该接口的实现类对象(动态代理实现),并且会自动交给IOC容器管理。
里面可以定义SQL语句,每一个查询行都会封装成一个对象,我们可以封装到一个集合当中,将查询语句返回值设置成集合即可。
配置IDEA SQL提示
1.选中SQL语句右键选择以下选项
2.配置MySQL数据库连接
JDBC简述
- sun公司提供了关系型数据库的接口。
- 厂商提供实现。实现又叫驱动。
- 我们使用接口编程,执行的代码时驱动jar包的实现类
JDBC使用方法
1.注册驱动
2.获取连接
3.创建对象执行SQL语句
4.解析结果
5.释放资源
数据库连接池
- 数据库连接池是一个容器,负责分配,管理数据库连接
- 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
- 释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
标准接口:DataSource
官方提供的数据库连接池接口,由第三方组织实现此接口
项目中最常用的两个数据库连接池为Druid连接池和Hikai连接池(Spring Boot默认)。
切换连接池:引入依赖即可
基础操作
1.删除
@Delete("delete from emp where id=#{id}")
public int delete(Integer id);
//返回值代表着操作记录数
注意:#{ ... }是一个占位符,里面的参数就是方法传递进来的参数,如果mapper接口方法形参只有一个普通类型的参数,则#{...}里面的属性名可以随便写。
我们查看Mybatis日志可以看到参数用占位符?数据库在执行SQL语句时会把传递的参数代替占位符。这种SQL语句叫预编译SQL。#{...}占位符就是使用预编译SQL,而${...}使用的是拼接SQL
预编译SQL:
性能更高:
java项目编写的SQL语句要执行,要先连接数据库,然后把SQL语句发送给MySQL数据库服务器之后,服务器会执行以下过程:为了提高效率,会将编译后的SQL语句给缓存起来。下一次执行SQL语句会先到缓存中直接找。如果没有再重新执行。
像上述三个语句需要编译三条SQL语句,而使用预编译的SQL只需要编译一次
更安全:
可以防止SQL注入。
像我们登入用户密码时候,假如输入的密码是一个'or'1'='1 ,那么数据发送到服务器之后密码使用拼接的方法就产生了一个永真语句。而使用预编译的方法就能解决。
2.新增
我们要接收的参数过多可以把数据封装到对象当中,insert只传递对象参数就可以。占位符里面传递的是对象的属性名
@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values (#{username), #{name}, #{gender}, #{ image) , #{ job}, #{entrydate}, #{deptId} , #{createTime}, #{updateTime}
public void insert (Emp emp) ;
主键返回:
描述:在数据添加成功后,需要获取插入数据库数据的主键。如:添加套餐数据时,还需要维护套餐菜品关系表数据。在默认情况下我们是接收不到数据库服务器返回的主键值。我们想要拿到主键值,我们要在增加接口的方法上添加下面注解。后面的true表示我们要拿到主键值,前面的id是主键封装在id这个属性当中。
@Options(keyProperty ="id", useGeneratedKeys = true)
3.更新
@Update("update emp set username = #{username}, name = #{name}, gender = #{gender}, image = #{image}, job = #{job}, entrydate = #{entrydate}, dept_id = #{deptId}, update_time = #{updateTime} where id = #{id
public void update (Emp emp) ;
4.查询
根据主键查询
@Select("select*from emp where id=#{id}")
public Emp getByid(Integer id);
实体类的属性名和数据库查询返回的字段名一致,Mybatis会自动封装。
实体类属性名和数据库表查询的返回字段名不一致,不能自动封装。
解决方法一:
给字段起别名,跟实体类中的属性一致。
方法二:通过@Results,@Result注解手动映射封装
方法三:开启Mybatis的驼峰命名的自动映射开关,将下述配置进配置文件中
条件查询:
@Select(select * from like'%${name}%' and gender =#{gender} and entrydate between #{begin}and order by #{end} desc)
public List<Emp> list(String name,Short gender,LocalDate begin,LocalDate end);
z注意:#{}占位符不能出现在' '当中,所以使用了${}占位符。还可以通过MySQL的concat函数解决
@Select(select * from likeconcat('%',#{name},'%') and gender =#{gender} and entrydate between #{begin}and order by #{end} desc)
public List<Emp> list(String name,Short gender,LocalDate begin,LocalDate end);
在SpringBoot的1.x版本和单独使用Mybatis,需要使用@param注解来完成映射
XML映射文件
使用Mybatis的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。
- XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)。
- XML映射文件的namespace属性为Mapper接口全限定名一致。
- XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
操作步骤
1.定义XML映射文件
2.把XML固定约束从官方文档拷贝过来
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zxt.mapper.EmployeeMapper">
</mapper>
3.mapper的namespace属性跟Mapper接口的全类名一致,sql语句的id跟接口名字一致
如果要更方便的查看Mapper接口和XML文件关联,可以下一个MybatisX插件
动态SQL
1.if标签
用于判断条件是否成立。使用test属性进行条件判断,如果条件为ture,则拼接SQL;
案例:根据名字,性别,查询员工,查询条件可只输入任意个
<select id="list" resultType="com. itheima.pojo. Emp">
select *
from emp
where
<if test="name != null">
name like concat('%', #{name}, '%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
order by update_time desc
</select>
但当我们第一个值为NULL时程序却发生了报错,这是因为我们的第二个值多出一个‘and’字符。我们就可以把where用标签包裹起来 。
where标签:
where元素只会在子元素有内容时候插入where子句。而且会自动去除自居的开头AND或OR
<select id="list" resultType="com. itheima.pojo. Emp">
select *
from emp
<where>
<if test="name != null">
name like concat('%', #{name}, '%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<where>
order by update_time desc
</select>
set标签
动态地在行首插入SET关键字,并会删掉额外的逗号。(用在update语句中)
案例:
<update id="update">
update emp
<set>
<if test="username != null">
username=#{username},
</if>
<if test="gender != null">
username=#{gender},
<if test="age != null">
username=#{age}
</if>
</if>
</set>
where id=#{id}
</update>
foreach标签
案例:前端返回为一个主键集合,根据主键批量删除
- collection:遍历的集合
- item:遍历出来的元素
- separator: 分隔符
- open:遍历开始前拼接的SQL片段
- close:遍历结束后拼接的SQL片段
案例:
<delete id="deleteByIds">
deletefrom emp where id in
<foreach colleqtion="ids" item="id" separator=", " open=" (" close=") ">
#{id}//代表每一次遍历出来的元素
</foreach>
</delete>
</mapper>
<sql>和<include>标签
如果在xml文件中存在大量的重复代码,那能够用这两个标签进行抽取注入。
<sql>负责抽取片段,有一个属性id。
<include>负责引用,有一个属性refid表示引用哪个片段,就是sql标签的id值
案例:
<sql> id="commonSelect">
select id, username, password, name, gender, image, job
from emp
</sql>
<include refid="commonSelect"/>