MyBatis
MyBatis
概述:MyBatis 是一款优秀的持久层(三层架构中的dao层)框架,用来简化jdbc的开发.
配置
导入依赖
<!--pom.xml-->
<!-- mybatis起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.5.14</version>
</dependency>
<!-- mysql驱动包-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
配置数据库连接的四要素
#配置数据库连接信息 四要素
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mydb01
#数据库连接的用户名
spring.datasource.username=root
#数据库连接的密码
spring.datasource.password=123456
新建Mapper接口
package com.springboot.Mapper;
import com.springboot.Pojo.MyUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper //在运行时,会自动生成该接口的实现类对象(代理对象),并且将该对象交给IOC容器管理
public interface UserMapper {
//查询全部用户信息
@Select("select * from user")
public List<MyUser> listUser();
}
使用javaBean类来结束数据库表
package com.springboot.Pojo;
public class MyUser {
private int id;
private String name;
private String password;
private String createTime;
private String updateTime;
private Short status;
public MyUser() {
}
public MyUser(int id, String name, String password, String createTime, String updateTime, Short status) {
this.id = id;
this.name = name;
this.password = password;
this.createTime = createTime;
this.updateTime = updateTime;
this.status = status;
}
@Override
public String toString() {
return "MyUser{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", createTime=" + createTime +
", updateTime=" + updateTime +
", status=" + status +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public Short getStatus() {
return status;
}
public void setStatus(Short status) {
this.status = status;
}
}
数据库连接池
- 数据库连接池是个容器,负责分配、管理数据库连接(Connectign)
- 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
- 释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
优势
- 资源重用
- 提升系统的响应速度
- 避免数据库连接重用
标准接口
javax.sql.DataSource接口- 官方提供的数据库连接池接口,由第三方组织实现此接口
- 功能:获取链接
Connection getConnection() throws SQLException
常见的数据库连接池
- DBCP
- C3P0
- Druid(德鲁伊连接池 是阿里巴巴开源的数据库连接池项目)
- HiKari(springBoot默认)
切换springBoot默认的连接池
切换德鲁伊连接池 官方地址
pom.xml
<!--加入依赖坐标-->
<dependency>
<groupld>com.alibaba</groupld>
<artifactld>druid-spring-boot-starter</artifactld>
<version>1.2.8</version>
</dependency>
lombok注解
Lombok是一个实用的Java类库,能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发、提高效率。
| 注解 | 作用 |
|---|---|
@Getter/@Setter | 为所有属性提供get/set方法 |
@ToString | 会给类自动生成易阅读的ToString方法 |
@EqualsAndHashCode | 根据类所拥有的非静态字段自动重写equals和hashCode方法 |
@Data | 提供了更综合的生成代码功能@Getter + @Setter + @ToString + @EqualsAndHashCode) |
@NoArgsConstructor | 为实体类生成无参的构造器方法 |
@AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有各参数的构造器方法, |
@RequiredArgsConstructor | 自动生成一个包含所有 final 字段或标记为 @NonNull 字段的构造方法*。通常用于依赖注入 |
加入依赖配置
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
使用
package com.springboot.Pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data //get/set/toString/equars/hashCode
@NoArgsConstructor //无参构造
@AllArgsConstructor//全参构造
public class MyUser {
private int id;
private String name;
private String password;
private String createTime;
private String updateTime;
private Short status;
}
注意
Lombok会在编译时,自动生成对应的java代码。我们使用lombok时,还需要安装一个lombok的插件(idea自带).。
Mybatis基础操作
配置Mybatis日志输出到控制台
#配置mybatis的日志 ,指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
参数占位符
#{...}:占位符,会将#{...}替换为?,生成预编译SQL,会自动设置参数值 推荐使用${...}:拼接符,直接将参数拼接在SOL语句中,存在SOL注入问题 如果对表名、列表进行动态设置时使用
@Mapper
public interface EmpMapper {
//获取所有员工信息
@Select("select * from emp")
public List<Emp> findAllEmp();
//根据id删除员工信息
//#{}参数占位符
//执行SQL时,会将#{...}替换为?,生成预编译SQL,会自动设置参数值。
//使用时机:参数传递,都使用#{...}
//${...}
// 拼接SQL。直接将参数拼接在SOL语句中,存在SOL注入问题。
// ·使用时机:如果对表名、列表进行动态设置时使用
@Delect("delete from emp where id=#{id}")
public void deleteEmpById(Integer id);
//新增员工信息
@Insert("insert into emp(username, password, name, sex, job, entry_date, dept_id, create_time, update_time) values (#{username}, #{password}, #{name}, #{sex}, #{job}, #{entryDate}, #{deptId}, #{createTime}, #{updateTime})")
public void saveEmp(Emp emp);
}
主键返回
描述:在数据添加成功后,需要获取插入数据库数据的主键,
如:添加套餐数据时,还需要维护套餐菜品关系表数据,
描述:在数据 添加成功后,需要获取插入数据库数据的主键。
如添加套餐数据时,还需要维护套餐菜品关系表数据
实现
keyProperty:需要往数据库表中添加的数据的主键值中封装
useGeneratedKeys:需要获取返回回来的主键值
@Options(useGeneratedKeys = true,keyProperty = "id")注解功能:会自动将生成的主键值赋值给emp对象的id属性
@Mapper
public interface EmpMapper {
//新增员工信息
//主键返回
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into emp(username, password, name, sex, job, entry_date, dept_id, create_time, update_time) values (#{username}, #{password}, #{name}, #{sex}, #{job}, #{entryDate}, #{deptId}, #{createTime}, #{updateTime})")
public void saveEmp(Emp emp);
}
数据封装
- 如果数据库字段名和实体类属性名一致时,
Mybatis会自动封装数据。 - 如果数据库字段名和实体类属性名不一致时,需要进行手动封装。
方案1:给字段起别名 让数据库字段名和别名一致
@Mapper
public interface EmpMapper {
//根据id查询员工信息=
//数据库字段名 别名
@Select("select id, username, password, name, sex, job, entry_date entryDate, dept_id deptId, create_time createTime, update_time updateTime from emp where id=#{id}")
public Emp findEmpById(Integer id);
}
方案二:使用@Results和@Result注解进行手动封装
@Mapper
public interface EmpMapper {
//方案二:使用`@Results`和`@Result`注解进行手动封装
@Results({
//手动映射 只需要对数据库字段名和实体类属性名不一致的进行映射
//column 数据库字段名
//property 实体类属性名
@Result(column = "entry_date", property = "entryDate"),
@Result(column = "dept_id", property = "deptId"),
@Result(column = "create_time", property = "createTime"),
@Result(column = "update_time", property = "updateTime")
})
@Select("select * from emp where id=#{id}")
public Emp findEmpById(Integer id);
}
方案三:开启Mybatis自动字段映射的开关
注意
Mybatis自动字段映射的开关,默认是关闭的,需要手动开启。- 自动字段映射只能在数据库字段为下划线命名规则时和实体类属性为驼峰命名规则时使用。
# resources/application.properties
# 开启mMybatis的驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true
条件查询
@Mapper
public interface EmpMapper {
//查询符合条件的员工信息
//name:模糊匹配
//sex:精准匹配
//job:精准匹配
//entry_date:范围匹配
//根据最后修改时间进行倒序排序
//在sql中 concat 函数用于将两个或多个字符串连接在一起
@Select("select * from emp where name like concat('%',#{name},'%') and sex=#{sex} and job=#{job} and entry_date between #{startDate} and #{endDate} order by update_time desc")
public List<Emp> findEmpByCondition(String name, Short sex, Short job, LocalDateTime startDate, LocalDateTime endDate);
}
//测试类
//查询符合条件的员工
@Test
public void textFindEmpByCondition() {
List<Emp> empList = empMapper.findEmpByCondition(
"张三",
(short) 1,
(short) 1,
LocalDateTime.of(2021, 1, 1, 12, 12, 12),
LocalDateTime.now());
System.out.println(empList);
}
xml映射文件
- XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
- XML映射文件的namespace属性为Mapper接口全限定名一致。
- XML映射文件中sql语句的id与Mapper 接口中的方法名一致,并保持返回类型一致。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springboot.Mapper.EmpMapper">
<!-- resultType:单条记录所封装的类型-->
<select id="findEmpByCondition" resultType="com.springboot.Pojo.Emp">
select * from emp where name like concat('%',#{name},'%') and sex=#{sex} and job=#{job} and entry_date between #{startDate} and #{endDate} order by update_time desc
</select>
</mapper>
动态sql标签
1. if标签 用于判断条件是否成立,使用text属性进行条件判断,如果条件为true,则拼接sql
注意
- 使用
where标签可以自动删除多余的and或or连接符 - 字句必须写
and或or
<select id="findEmpBydynamic" resultType="com.springboot.Pojo.Emp">
select * from emp
-- where标签 动态生成where语句 如果where语句中的条件都不成立则不会生成where
-- 根据条件判断是否删除第二个条件之后的and或or连接符(**`where` 对`and`或`or`的处理是删除不是生成**)
<where>
<if test="name!=null">name like concat('%',#{name},'%')</if>
<if test="sex!=null ">and sex=#{sex}</if>
<if test="job!=null">and job=#{job}</if>
<if test="startDate!=null and endDate!=null ">and entry_date between
#{startDate} and #{endDate}
</if>
</where>
</select>
动态更新员工信息
注意
- 使用
set标签可以自动删除多余的,连接符 - 字句必须写
,
<!-- 动态更新员工信息-->
<update id="updateEmpDynamic">
update emp
<!-- 动态地在行首插入 SET关键字,并会删掉额外的逗号。(用在update语句中)-->
<set>
<if test="username!=null">username=#{username}</if>
<if test="name!=null">name=#{name}</if>
<if test="sex!=null">,sex=#{sex}</if>
<if test="job!=null">,job=#{job}</if>
<if test="entryDate!=null">,entry_date=#{entryDate}</if>
<if test="deptId!=null">,dept_id=#{deptId}</if>
update_time=#{updateTime}
</set>
where id=#{id}
</update>
forEach标签
批量删除员工信息
<!-- 批量删除员工信息-->
<!-- collection:要遍历的集合-->
<!-- item:遍历出来的单个元素-->
<!-- separator:分隔符-->
<!-- open:遍历开始前拼接的sql片段-->
<!-- close:遍历结束后拼接的sql片段-->
<delete id="deleteEmpByIds">
delete
from emp
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
sql判断标签 <sql>和<include>标签
<sql>标签用于抽取重复的sql片段,<sql>标签中的内容不会直接执行,只有被引用的时候才会执行。<include>标签用于引用<sql>标签中的内容,<include>标签中的内容会直接执行。
<!-- sql片段标签-->
<sql id="commonSelect">
select name, sex, job, entry_date, dept_id, create_time, update_time
from emp
</sql>
<!-- 使用sql片段查询员工数据-->
<select id="selectEmpUserById" resultType="com.springboot.Pojo.Emp">
<include refid="commonSelect"/>
where id=#{id}
</select>