文章目录
什么是MyBatis
MyBatis是一种优秀的持久层框架,用于简化JDBC的开发
持久层:指的就是持久化操作的层, 通常指数据访问层(dao), 是⽤来操作数据库的。
MyBatis的写法
- xml
- 注解
注解
1.引入MyBatis依赖,引入对应数据库的依赖,比如mysql
2.配置数据库相关信息
3.定义Java对象
4.写实现
package com.example.demo.mapper;
import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserInfoMapper {
@Select("select * from userinfo")
List<UserInfo> selectAll();
}
逻辑删除和物理删除:
逻辑删除:从逻辑上删除(推荐)
物理删除:从硬盘中进行数据删除 delete
单元测试
在创建出来的SpringBoot工程中,在src下的test⽬录下,已经⾃动帮我们创建好了测试类 ,我们可以直接使⽤这个测试类来进⾏测试。
在需要写单元测试的类中右键点击generate
,选择Test
勾选需要的东西,生成类:
然后编写测试方法:
package com.example.demo.mapper;
import com.example.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@Slf4j
@SpringBootTest
class UserInfoMapperTest {
@Autowired
private UserInfoMapper userInfoMapper;
@BeforeEach
void setUp() {
log.info("setUp");
}
@AfterEach
void tearDown() {
log.info("After");
}
@Test
void selectAll() {
List<UserInfo> list = userInfoMapper.selectAll();
log.info(list.toString());
}
}
使用MyBatis可能会遇到的问题
- 没有配置数据库相关信息
- 账号密码错误
- 数据库错误
-
表不存在
-
字段错误
MyBatis基础操作
MyBatis的增, 删, 改操作
打印日志
配置yml:
mybatis:
configuration: # 配置打印 MyBatis⽇志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
参数传递
查询id=1的用户
@Select("select * from userinfo where id= 1")
UserInfo selectOne();
这样的话, 只能查找id=1 的数据, 所以SQL语句中的id值不能写成固定数值,需要变为动态的数值解决⽅案:在queryById⽅法中添加⼀个参数(id),将⽅法中的参数,传给SQL语句使⽤ #{} 的⽅式获取⽅法中的参数。
@Select("select * from userinfo where id= #{id}")
UserInfo selectOne(Integer id);
添加测试用例:
@Test
void selectOne() {
log.info(userInfoMapper.selectOne(1).toString());
}
运行结果:
使⽤ @Param
设置别名, #{...}
⾥⾯的属性名必须和
@Param
设置的⼀样。
@Select("select * from userinfo where id= #{userId}")
UserInfo selectOne2(@Param("userId") Integer id);
增(Insert)
增加一个用户
@Insert("insert into userinfo (username,password,age,gender,phone)" +
"values(#{username},#{password},#{age},#{gender},#{phone})")
Integer insert(UserInfo userInfo);
添加测试用例:
@Test
void insert() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("zhaoliu");
userInfo.setPassword("zhaoliu");
userInfo.setAge(6);
userInfo.setGender(0);
userInfo.setPhone("123456789");
Integer result = userInfoMapper.insert(userInfo);
log.info("insert 方法,执行结果:{}",result);
}
获取自增id
//返回自增id
@Options(useGeneratedKeys = true, keyProperty = "id")
对Insert的参数进行重命名
参数为对象时,对参数重命名
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into userinfo (username,password,age,gender,phone)" +
"values(#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender},#{userInfo.phone})")
Integer insert2(@Param("userInfo") UserInfo userInfo);
删(Delete)
删除id为5的用户
@Select("delete from userinfo where id = #{id}")
Integer delete(Integer id);
测试:
@Test
void delete() {
userInfoMapper.delete(5);
}
执行成功了
数据库中id为5的用户已经删了
改(Update)
将id等于4的年龄改为16
@Update("update userinfo set age = #{age} where id = #{id}")
Integer update(Integer id);
测试:
@Test
void update() {
UserInfo userInfo = new UserInfo();
userInfo.setAge(16);
userInfo.setId(4);
Integer result = userInfoMapper.update(userInfo);
if (result > 0){
log.info("数据修改成功");
}
}
查(Select)
结果映射,MyBatis会自动的根据数据库的字段名和Java对象的属性名,进行映射,如果名称一样就进行赋值。
- 对mysql查询结果进行重命名
/**
* 结果映射
* 方法一:对字段进行重命名
* @return
*/
@Select("select id, username, password, age, gender, phone," +
" delete_flag as deleteFlag, create_time as createTime, update_time as updateTime" +
" from userinfo")
List<UserInfo> selectAll();
测试:
@Test
void selectAll() {
List<UserInfo> list = userInfoMapper.selectAll();
log.info(list.toString());
}
- 使用
@Results
/**
* 结果映射
* 方法二:使用注解的方式
* @return
*/
@Results({
@Result(column = "delete_flag",property = "deleteFlag"),
@Result(column = "create_time",property = "createTime"),
@Result(column = "update_time",property = "updateTime"),
})
@Select("select * from userinfo")
List<UserInfo> selectAll2();
测试 :
@Test
void selectAll2() {
List<UserInfo> list = userInfoMapper.selectAll2();
log.info(list.toString());
}
如何复用@Results
的定义
/**
* 结果映射
* 方法二:使用注解的方式
* @return
*/
@Results(id = "BaseMap",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> selectAll2();
@ResultMap(value = "BaseMap")
@Select("select * from userinfo where id= #{id}")
UserInfo selectOne(Integer id);
- 使用配置的方式,自动转驼峰
mybatis:
configuration: # 配置打印 MyBatis⽇志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true #配置驼峰自动转换
/**
* 结果映射
* 方法三:使用配置的方式,自动转驼峰
* @return
*/
@Select("select * from userinfo")
List<UserInfo> selectAll3();
运行测试:
@Test
void selectAll3() {
List<UserInfo> list = userInfoMapper.selectAll3();
log.info(list.toString());
}
XML
- 配置数据库
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
- 指明xml的路径
- 写xml的实现
<?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.example.demo.mapper.UserInfoXMLMapper">
<select id="selectAll" resultType="com.example.demo.model.UserInfo">
select * from userinfo;
</select>
</mapper>
@Mapper
public interface UserInfoXMLMapper {
List<UserInfo> selectAll();
}
测试:
@Slf4j
@SpringBootTest
class UserInfoXMLMapperTest {
@Autowired
private UserInfoXMLMapper userInfoXMLMapper;
@Test
void selectAll() {
List<UserInfo> userInfos = userInfoXMLMapper.selectAll();
log.info(userInfos.toString());
}
}
常见问题
可能原因:
xml
和接口定义的方法名不一致mapper
的路径配置和xml
的路径不一样xml
namespace
写错了