在应⽤分层学习时, 我们了解到web应⽤程序⼀般分为三层,即:Controller、Service、Dao .之前的案例中,请求流程如下: 浏览器发起请求, 先请求Controller, Controller接收到请求之后, 调⽤Service进⾏业务逻辑处理, Service再调⽤Dao, 但是Dao层的数据是Mock的, 真实的数据应该从数据库中读取。我们学习MySQL数据库时,已经学习了JDBC来操作数据库, 但是JDBC操作太复杂了,所以我们学习使用MyBatis。
一.什么是MyBatis?
- MyBatis是⼀款优秀的 持久层 框架,⽤于简化JDBC的开发。
- MyBatis本是 Apache的⼀个开源项⽬iBatis,2010年这个项⽬由apache迁移到了google code,并且改名为MyBatis 。2013年11⽉迁移到Github。
在上⾯我们提到⼀个词:持久层
持久层:指的就是持久化操作的层, 通常指数据访问层(dao), 是⽤来操作数据库的
举个栗子~
- 就像餐馆老板不需要亲自去后厨找每一种食材一样,MyBatis 封装了 JDBC(Java Database Connectivity)的复杂操作,如加载数据库驱动、建立连接、创建 SQL 语句等。这样,开发者就可以专注于编写 SQL 语句本身,而不需要处理这些底层的、繁琐的数据库连接工作。
二.创建工程
1.创建springboot⼯程,并导⼊ mybatis的起步依赖、mysql的驱动包
- 项⽬⼯程创建完成后,⾃动在pom.xml⽂件中,导⼊Mybatis依赖和MySQL驱动依赖
2.数据库创建用户表(userinfo)
3.创建⽤⼾表, 并创建对应的实体类User
代码:
package com.example.demo.model;
import lombok.Data;
import java.util.Date;
@Data
public class UserInfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
4.通过yml文件配置数据库连接字符串
- 同时加上mybatis打印⽇志(方便我们进行日志查看)
连接数据库代码:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: weigang527
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis打印日志代码:
mybatis:
# 配置 mybatis xml 的文件路径,在 resources/mapper 创建所有表的 xml 文件
mapper-locations: classpath:mybatis/**Mapper.xml
configuration: # 配置打印 MyBatis日志
如果是application.properties⽂件, 配置内容如下:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3 #数据库连接的url
4 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=false
5 #连接数据库的⽤⼾名
6 spring.datasource.username=root
7 #连接数据库的密码
8 spring.datasource.password=root
5.在项⽬中, 创建持久层接⼝UserInfoMapper(声明方法)
比如我要查询整张表
package com.example.demo.mapper;
import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserInfoMapper {
@Select("select * from userinfo")
List<UserInfo> getUserInfoAll();
}
6.单元测试
点击鼠标右键
代码:
@Test
void getUserInfoAll() {
System.out.println(userInfoMapper.getUserInfoAll());
}
7.查看
三.增删改查操作
3.1删除(delete)
1.接口方法声明
@Select("select * from userinfo where delete_flag = #{deleteFlag}")//#{deleteFlag}类似占位符?
List<UserInfo> getUserInfoByDeleteFlag(Integer deleteFlag);
2.单元测试(鼠标右键)
3.运行
如果只有一个参数,参数名可以不一样,随便怎么修改
3.2查询(select)
查询条件(gender = 2,delete_flag = 0)
有多个参数时,此时我要查询数据库的wangwu
1.接口中声明方法
代码:
@Select("select * from userinfo where delete_flag = #{deleteFlag} and gender= #{gender}")
List<UserInfo> getUserInfo2( Integer deleteFlag, Integer gender);
2. 进行单元测试
@Test
void selectUserInfos2() {
System.out.println(userInfoMapper.selectUserInfos());
}
3.查询成功
3.3插入(insert)
插入操作:
插入成功,返回一个整数(影响的行数)
当调用这个方法时,需要传入一个UserInfo
对象。MyBatis会自动将这个对象的属性值与SQL语句中的参数占位符匹配,并执行插入操作。
1.方法声明
代码:
@Insert("insert into userinfo (username, password, age, gender) values (#{username},#{password},#{age},#{gender})")
Integer insert(UserInfo userInfo);
2.进行单元测试
代码:
@Test
void insert() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("zhaoliu6666");
userInfo.setPassword("88888");
userInfo.setAge(18);
userInfo.setGender(1);
Integer result = userInfoMapper.insert(userInfo);
System.out.println("result: "+result + ",id:"+userInfo.getId());
}
3.插入成功
补充:有自增id的注解
@Options(useGeneratedKeys = true, keyProperty = "id")
3.4删除
删除id为6的信息
1.方法声明
代码:
@Delete("delete from userinfo where id = #{id}")
Integer delete(Integer id);
2.单元测试
@Test
void delete() {
System.out.println("删除数据: "+ userInfoMapper.delete(6));
}
3.删除成功
3.4更新(update)
更新id为1的用户信息
1.方法声明
代码:
@Update("update userinfo set password = #{password}, age = #{age}, gender = #{gender} where id = #{id}")
Integer update(UserInfo userInfo);
2.单元测试
代码:
@Test
void update() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setPassword("123456");
userInfo.setAge(56);
userInfo.setGender(2);
Integer result = userInfoMapper.update(userInfo);
System.out.println("更新影响行数: "+result);
}
3.更新成功
3.5属性无法映射
查询是最简单的语句,但是我们这里增添了难度。
当数据库和对象的属性不对应时,显示为null。
1.方法声明
代码:
@Select("select * from userinfo")
List<UserInfo> getUserInfoAll();
2.单元测试
代码:
@Test
void getUserInfoAll() {
System.out.println(userInfoMapper.getUserInfoAll());
}
日志打印:
3.5.1起别名
解决办法1:使用SQL语句起别名的方式。
1.在声明方法中添加属性
代码:
@Select("SELECT id, username, password, age, gender, phone, " +
"delete_flag as deleteFlag, create_time as createTime, update_time as updateTime " +
"FROM `userinfo`")
List<UserInfo> selectUserInfos();
2.单元测试
@Test
void selectUserInfos() {
System.out.println(userInfoMapper.selectUserInfos());
}
3.显示成功
3.5.2结果映射
1.声明方法中添加@Results注解
@Results(id ="resultMap" , value = {
@Result(column = "delete_flag", property = "deleteFlag"),
@Result(column = "create_time", property = "createTime"),
@Result(column = "update_time", property = "updateTime")
})
@Select("SELECT * FROM `userinfo`")
List<UserInfo> selectUserInfos2();
2.单元测试
@Test
void selectUserInfos2() {
System.out.println(userInfoMapper.selectUserInfos());
}
3.打印成功
3.5.3驼峰转换
在yml文件进行配置:
map-underscore-to-camel-case: true #配置驼峰自动转换