欢迎 👍点赞 ➕关注 ❤️收藏 💬评论
🍨一、什么MyBatis?
🍦定义
MyBatis是一款持久层(用来操作数据库的)框架 ,主要用于Java语言开发,专注于解决数据库操作与Java对象之间的映像问题,简化JDBC(Java数据库连接)的开发流程。
- 其核心思想是将SQL语句与Java代码分离,通过XML或注解的方式定义SQL,在由MyBatis自动完成Java对象与数据库记录之间的映射(即"ORM映射",Object-)
🍨二、准备工作
🍧1.引入依赖、mysql驱动包

🍧2.数据准备

🍧3.配置数据库连接字符串
yml文件
javascript
spring:
application:
name: spring-mybatis-demo
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 111
driver-class-name: com.mysql.cj.jdbc.Driver
properties文件
javascript
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=false
#连接数据库的⽤⼾名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=root
- 这里的用户名和密码要修改成自己的,否则无法连接到数据库。
🍧4.持久层
javascript
@Mapper
public interface UserMapper {
//查询注解
@Select("select * from user_info")
//接口定义方法:查询查询用户
List<UserInfo> qurryAllUser();
}
- Mybatis的持久层接口规范一般定义为XxxMapper;
- Mapper层为接口类型;
- 使用@Select注解,用于执行SQL语句;
- 表名需要与数据库一致
- 接口定义方法:返回结果类型 方法名
🍧5.单元测试
快速创建对应的单元测试



- 在对应的名称上右键->Generate->Test->勾选
@Test
java
@SpringBootTest
class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
void qurryAllUser() {
List<UserInfo> userInfos=userMapper.qurryAllUser();
System.out.println(userInfos);
}
}

除了@Test注解,这里还有@BeforeEach和@AfterEach注解
@BeforeEach和@AfterEach
@BeforeEach:在每个**@Test执行之前**执行,与位置无关(可以初始化代码等...)
@AfterEach:在每个**@Test执行之后**执行,与位置无关(可以清理资源)
java
@SpringBootTest
class UserMapperTest {
@Autowired
private UserMapper userMapper;
@BeforeEach
void selectId() {
String userName=userMapper.querryById(2);
System.out.println(userName);
}
@AfterEach
void selectId2() {
String userName=userMapper.querryById(3);
System.out.println(userName);
}
@Test
void qurryAllUser() {
List<UserInfo> userInfos=userMapper.qurryAllUser();
System.out.println(userInfos);
}
}

这里有一个问题了
明明在数据库中我是有数据的,但是为什么这里的deleteFalg、createTime、updateTime是null???

原因:UserInfo实体类中deleteFalg、createTime、updateTime与数据库表中的字段名不一致,没有进行正确的映射。
**这里提供了几种解决方案:**起别名、结果映射、开启驼峰命名
🍧6.数据库字段与实体类属性命名不一致问题的解决方案
1.起别名
javascript
@Select("select id,username,password,age,gender,phone," +
"delete_flag as deleteFalg,create_Time as createTime,update_Time as updateTime" +
" from user_info")
List<UserInfo> qurryAllUser2();
测试
javascript
@Test
void qurryAllUser2() {
List<UserInfo> userInfoList=userMapper.qurryAllUser2();
System.out.println(userInfoList);
}

2.结果映射(@Results和@Rsult)
javascript
@Select("select id,username,password,age,gender,phone,delete_flag,create_Time ,update_Time from user_info")
@Results({
@Result(column="delete_flag",property="deleteFlag"),
@Result(column="create_Time",property="createTime"),
@Result(column="update_Time",property="updateTime"),
})
List<UserInfo> queryAllUser3();
- @Results/@Result:用于指定数据库字段(colmn) 和**实体类的属性(property)**之间的映射关系;
- 注意:是**@Results** 一个注解包裹**@Result**多个注解。
测试
javascript
@Test
void qurryAllUser3() {
List<UserInfo> userInfoList=userMapper.queryAllUser3();
System.out.println(userInfoList);
}
结果

但是这里有一个问题,如果其他的SQL映射语句,我也需要进行deleteFalg、createFlag、updateFlag的映射呢?那我们是不是要再写一遍?那不是会造成代码冗余?
那这里有一个注解@ResultMap用来复用结果映射逻辑,减少代码冗余。
复用结果映射逻辑@ResultMap
javascript
@Select("select id,username,password,age,gender,phone,delete_flag,create_Time ,update_Time from user_info")
@Results(id="resultMap",value = {
@Result(column="delete_flag",property="deleteFlag"),
@Result(column="create_Time",property="createTime"),
@Result(column="update_Time",property="updateTime"),
})
List<UserInfo> queryAllUser3();
@Select("select id,username,password,age,gender,phone,delete_flag," +
"create_Time ,update_Time from user_info where username=#{username}")
@ResultMap(value = "resultMap")
UserInfo queryByName(String username);

测试
javascript
@Test
void querryByName() {
System.out.println(userMapper.queryByName("zhaoliu"));
}
结果

3.开启驼峰命名自动映射
在yml中进行配置
javascript
mybatis:
configuration:
map-underscore-to-camel-case: true #配置驼峰自动转换
- 作用:将xx_xx->xxXx,全局生效
无需在映射或起别名
javascript
@Select("select id,username,password,age,gender,phone,delete_flag," +
"create_Time ,update_Time from user_info where username=#{username}")
UserInfo queryByName2(String username);
测试
javascript
@Test
void queryByName2() {
System.out.println(userMapper.queryByName2("zhaoliu"));
}
结果

🍨三、配置日志的打印
yml
javascript
mybatis:
configuration: # 配置打印 MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
再次运行之前的测试

打印日志的核心作用
- 查看最终执行的语句及参数,验证映射和动态SQL是否正确;
- 排查数据异常;
- 分析执行耗时,优化性能。
🍨四、参数传递(#{})
- 使用#{value},动态传参
- value建议与参数名一致
🎂单个参数
javascript
@Select("select username from user_info where id=#{id}")
String querryById(Integer id);
🎂多个参数
javascript
@Select("select * from where id=#{id} and name=#{name}")
List<UserInfo> selectIdAndName(Integer id,Integer name);
🎂参数重命名@Param
javascript
@Select("select username from user_info where id=#{id}")
String querryById2(@Param("userId")Integer id);

🍨五、MyBatis的基础操作
🍰 1.增(Insert)
普通新增
javascript
//新增:返回受影响的行数
@Insert("Insert into user_info(username,password,age,gender,phone)" +
"value(#{username},#{password},#{age},#{gender},#{phone})")
Integer insertUserInfo(UserInfo userInfo);
- 数据的添加使用@Insert注解;
- 返回结果类型为Integer,因为新添数据,返回的是受影响的函数
测试
java
@Test
void insertUserInfo() {
UserInfo userInfo=new UserInfo();
userInfo.setUsername("小哈");
userInfo.setPassword("12345");
userInfo.setAge(4);
userInfo.setGender(1);
userInfo.setPhone("124546572");
userMapper.insertUserInfo(userInfo);
}

新增并返回自增主键(options)
语法
javascript
@Options(useGeneratedKeys = true,keyProperty = "id")
- useGeneratedKeys:获取自动生成主键功能,默认为false;
- keyProperty:指定将生成的主键赋值给哪个属性(这个属性需要与实体类一致)。
原因
当操作存在关联关系的表的时候(如"订单表"和"订单项表"),订单项需要关联订单的主键作为外键。
- 先插入订单,生成自增主键;
- 需要立即获得这个主键,才能插入对应的订单项,否则订单项无法关联到订单。
使用
javascript
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("Insert into user_info(username,password,age,gender,phone)" +
"value(#{username},#{password},#{age},#{gender},#{phone})")
Integer insertUserInfo(UserInfo userInfo);
测试
java
@Test
void insertUserInfo() {
UserInfo userInfo=new UserInfo();
userInfo.setUsername("小哈");
userInfo.setPassword("12345");
userInfo.setAge(4);
userInfo.setGender(1);
userInfo.setPhone("124546572");
userMapper.insertUserInfo(userInfo);
System.out.println("数据id: "+userInfo.getId());
}

🍰 2.删(delete)
删除
javascript
@Delete("delete from user_info where username=#{username}")
Integer deldeteUserName(String username);
测试
java
@Test
void deldeteUserName() {
userMapper.deldeteUserName("小哈");
}

🍰 3.改(update)
更新
javascript
@Update("update user_info set username=#{username} where id=#{id}")
Integer updateUserName(UserInfo userInfo);
测试
java
@Test
void updateUserName() {
UserInfo userInfo=new UserInfo();
userInfo.setUsername("zhaoliu");
userInfo.setId(2);
userMapper.updateUserName(userInfo);
}

改前

改后

还有查找(select),我们前面也有使用到,这里就不多写了。

