目录
前言:本篇主要是简单快速上手使用为目的,讲解不是很深入
一:简介
1.诞生
传统的数据库操作,如JDBC在执行一个简单的操作,都需要写一大堆代码,大大降低了在开发环境中的工作效率,为此将传统的JDBC复杂冗余的操作进行封装---mybatis
2.mybatis了解
1>:MyBatis 是一款优秀的 Java 持久层框架(ORM 框架)
2>: 对原生 JDBC 的封装和增强,是代码与数据库之间的桥梁, 数据可以通过mybatis操作快速永久性存储在数据库中
3>:可以简化 Java 程序对数据库的 CRUD 操作,消除 JDBC 原生开发的冗余代码,同时兼顾 SQL 的灵活性
4>:mybatis的核心特点 配置映射 + 底层封装 JDBC
简单来说:开发者只需要关注「写 SQL语句」和「调用方法」,剩下的所有 JDBC 繁琐操作,MyBatis 全帮你做了
二:使用
1.项目环境配置
1>:依赖导入
在创建项目时导入:

mybatis Framework:把 MyBatis 框架引入 Spring Boot 项目,让项目能通过 MyBatis 操作数据库(写 SQL、映射数据等)
mysql driver: 是 Java 程序连接 MySQL 数据库的驱动包;
pom文件依赖导入:
看自己的mybatis-spring-boot-starter版本与spring-boot版本是否匹配
对应链接:Introduction -- mybatis-spring-boot-autoconfigure
yml配置:
java
spring:
application:
name: spring-batis-12-29
# 数据库连接配置
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false #连接url
username: root # 用户名
password: "123456" # 密码,数字加上引号
driver-class-name: com.mysql.cj.jdbc.Driver # 驱动类型
mybatis:
configuration: # 配置打印 MyBatis⽇志,让 MyBatis 执行的 SQL 语句打印到控制台
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
文件创建:
前提首先提前准备好操作的数据库

接着创建接口并添加注解
java
@Mapper
public interface UserInfoMapper {
// 可以书写mybatis代码
}
2.mapper数据库操作
1>:映射规则
mybatis主要作用在于映射: 会将查找的mysql按照字段名(若有下换线分割,则 去除下划线+小驼峰形式 ) ,并在java定义的类中寻找对应的相匹配的属性名进行一一赋值
比如: mysql中的字段名称为: user_name ,到java中就会找 userName字段进行赋值
特殊注意:若字段存在下换线分割时,必须添加依赖才会自动匹配--->后面会重点讲到
还要创建一个用于接受返回值的类:
java
@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;
}
2>: insert**:密码等于李四的基本信息**
代码:
java
@Select("select * from user_info where `password` = 'lisi'")
UserInfo selectByPass();
此时检验代码要么Controller类调用Service类,一步步到selectById方法,要么生成单元测试

执行测试:
java
@SpringBootTest
class UserInfoMapperTest {
// 注入代理对象
@Autowired
private UserInfoMapper userInfoMapper;
@BeforeEach
void setUp() {
System.out.println("在测试之前执行");
}
@AfterEach
void tearDown() {
System.out.println("在测试之后执行");
}
@Test
void selectByPass() {
UserInfo userInfo = userInfoMapper.selectByPass();
System.out.println(userInfo);
}
}

3>:insert:一个参数的基本查找信息
方法一:直接传递参数
代码:
java
@Select("select * from user_info where `password` = #{pass}")
UserInfo selectByPassAndOneVar(String pass);
测试代码:
java
@Test
void selectByIdAndOneVar() {
System.out.println(userInfoMapper.selectByPassAndOneVar("lisi"));
}

方法二:设置别名
代码:
java
@Select("select * from user_info where `password` = #{p}")
UserInfo selectByPassAndOneVar(@Param("p") String pass);
4>:insert:多个参数的基本查找信息
方法一:直接传递参数
代码:
java
@Select("select * from user_info where id = #{id} or `password` = #{pass} ")
List<UserInfo> selectSomeVar(Integer id,String pass);
测试代码:
java
@Test
void selectSomeVar() {
List<UserInfo> userInfoList = userInfoMapper.selectSomeVar(1, "zhangsan");
userInfoList.forEach(System.out::println);
}

方法二:传递对象
mybatis本质就是映射,只要把该对象传递,他会寻找名字相同的变量进行自动匹配
代码:
java
@Select("select * from user_info where id = #{id} or `password` = #{password} ")
List<UserInfo> selectSomeVar(UserInfo userInfo);
测试代码:
java
@Test
void selectSomeVar() {
UserInfo userInfo = new UserInfo();
userInfo.setId(3);
userInfo.setPassword("zhangsan");
List<UserInfo> userInfoList = userInfoMapper.selectSomeVar(userInfo);
userInfoList.forEach(System.out::println);
}

5>:处理值不正确情况
通过观察上述情况,发现每一次查找在mysql的返回值中,delete_flag、create_time与update_time字段明明有值,但是打印的值却是空的
**原因:**还是那句话,mybatis本质就是映射
当我们执行并调用对应的方法,实际上是代理对象 先从方法中读取并匹配参数 ,接着去对应的数据库查找并将返回的值按照名字相同进行赋值,此处就是因为对象名字与字段名字不匹配导致赋值失败
**解决办法一:**主动修改对象属性名为小写蛇形(可以,但不符合java命名规范)
**解决办法二:**使用注解Results进行重命名

测试代码:
java
@Test
void selectSomeVar() {
UserInfo userInfo = new UserInfo();
userInfo.setId(3);
userInfo.setPassword("zhangsan");
List<UserInfo> userInfoList = userInfoMapper.selectSomeVar(userInfo);
userInfoList.forEach(System.out::println);
}

解决办法三 :加上配置,mybaits此时会将sql中的字段去除下划线+小驼峰重新拼接,此时就与属性名相同
java
mybatis:
configuration:
map-underscore-to-camel-case: true #配置驼峰⾃动转换
将Results注解屏蔽后执行结果:

6>: insert**:一行数据**
**方法一:**直接在方法参数传入值
**方法二:**传递对象,利用映射规则把属性值映射在sql语句中
代码:
java
@Insert("insert into user_info(username,`password`,age,gender,phone) " +
"values (#{username},#{password},#{age},#{gender},#{phone})")
Integer InsertRowValues(UserInfo userInfo);
测试代码:
java
@Test
void insertRowValues() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("赵六");
userInfo.setPassword("zhaoliu");
userInfo.setAge(22);
userInfo.setGender(0);
userInfo.setPhone("11223344");
int result = userInfoMapper.InsertRowValues(userInfo);
System.out.println("影响行数>:"+result);
}

**方法三:**使用parm修改对象名
需要注意点:若是普通成员重命名依然可以传递:若是对象进行重命名,会被认为是个普通变量,此时 新名字+ '.' +属性才可以访问内部
代码:
java
@Insert("insert into user_info(username,`password`,age,gender,phone) " +
"values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone})")
Integer InsertRowValues(@Param("U") UserInfo userInfo);

7>:insert:拿到新添加的数据
当我们新增加一行数据后,可能需要拿到这行数据某个值进行各种crud等操作,如何拿到??
方法一:方法返回值变为对象
此时会按照映射规则把字段赋值给属性(名称不一样注意加注解/配置)
方法二:使用注解@Options(useGeneratedKeys = true, keyProperty = "id")
useGeneratedKeys: 表示"开启'使用数据库生成的主键'"
**keyProperty:**把自增主键赋值给实体类的哪个属性
代码:
java
@Insert("insert into user_info(username,`password`,age,gender,phone) " +
"values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone})")
@Options(useGeneratedKeys = true,keyProperty = "id")
Integer InsertRowValues(@Param("U") UserInfo userInfo);
测试代码:
java
@Test
void insertRowValues() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("赵六");
userInfo.setPassword("zhaoliu");
userInfo.setAge(22);
userInfo.setGender(0);
userInfo.setPhone("11223344");
int result = userInfoMapper.InsertRowValues(userInfo);
System.out.println("对象内的值>:"+userInfo.getId());
System.out.println("影响行数>:"+result);
}

可以看到,这个option 会自动回填主键的值,并且在select不生效
8.delete:删除一行数据
delete只能返回void或Integer
代码:
java
@Delete("delete from user_info where id = #{id}")
Integer DeleteById(Integer id);
测试代码:
java
@Test
void deleteById() {
Integer digital = userInfoMapper.DeleteById(6);
System.out.println(digital);
}

9>:update:更新一条数据
代码:
java
@Update("update user_info set age = 43 where username = 'lisi'")
Integer UpdateByUser();
测试代码:
java
@Test
void updateByUser() {
Integer digital = userInfoMapper.UpdateByUser();
System.out.println(digital);
}

3.xml数据库操作
1>:配置与创建
通过配置xml文件进行操作数据库,思路为:

稍微提取一下:项目加载提取配置 --->根据namepace等配置statement对象放入缓存--->代理对象根据全限定方法名称查找对象并执行sql语句--->进行数据库交互 --->结果处理员与返回
可以看到我们需要: xml配置、数据库配置、xml与接口的关联、结果处理
开始配置:

将以下文件配置导入UserInfoXmlMapper文件中,重新创建并将对应接口的全限定名称加入namespace中
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">
<!--添加自己的配置-->
</mapper>
xml里面只需要注意格式,其他内容完全与注解操作一样
2>:select:查询一条数据
第一个:普通查找
代码:
XML
<select id="selectById" resultType="com.example.demo.Entity.UserInfo">
<!-- id为方法名,返回值只有select存在,且类型必须加上全限定类名-->
select * from user_info where `password` = 'lisi'
</select>
java
UserInfo selectById();
测试代码:
java
@Test
void selectById() {
System.out.println(userInfoXmlMapper.selectById());
}

第二个:重命名参数查找
代码:
XML
<select id="selectByPassAndOneVar" resultType="com.example.demo.Entity.UserInfo">
select * from user_info where `password` = #{p}
</select>
java
UserInfo selectByPassAndOneVar(@Param("p") String pass);
测试代码:
java
@Test
void selectByPassAndOneVar() {
System.out.println(userInfoXmlMapper.selectByPassAndOneVar("lisi"));
}

第三个:处理为空情况
在上面介绍我们可以配置mybatis自动驼峰转换 与用as起别名 ,也可以用Results注解进行映射,在xml中则使用
代码:
XML
<!-- 模仿注解Results-->
<!-- id:给当前标签起个名字 type:返回的实体的全限定类名-->
<resultMap id="XmlResults" type="com.example.demo.Entity.UserInfo">
<!-- 里面与Result一样-->
<result column="delete_flag" property="deleteFlag"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</resultMap>
<!-- 使用了resultMap标签后,select中不允许resultType-->
<select id="selectSomeVar" resultMap="XmlResults">
select * from user_info where id = #{id} or `password` = #{password}
</select>
java
List<UserInfo> selectSomeVar(UserInfo userInfo);
测试代码:
java
@Test
void selectSomeVar() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setPassword("zhaoliu");
List<UserInfo> userInfoList = userInfoXmlMapper.selectSomeVar(userInfo);
userInfoList.forEach(System.out::println);
}

3>:insert:添加一条数据
第一个:普通添加
注意:insert update update默认返回影响行数,标签不写返回类型,否则会报不支持返回值的错
代码:
XML
<insert id="InsertRowValues" >
insert into user_info(username,`password`,age,gender,phone)
values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone});
</insert>
java
Integer InsertRowValues(@Param("U") UserInfo userInfo);
测试代码:
java
@Test
void insertRowValues() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("赵六");
userInfo.setPassword("zhaoliu");
userInfo.setAge(22);
userInfo.setGender(0);
userInfo.setPhone("11223344");
Integer integer = userInfoXmlMapper.InsertRowValues(userInfo);
System.out.println("影响行数>:"+integer);
}

第二个:拿到自增主键
代码:
XML
<insert id="InsertRowValues" useGeneratedKeys="true" keyProperty="id">
insert into user_info(username,`password`,age,gender,phone)
values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone});
</insert>
java
List<UserInfo> selectSomeVar(UserInfo userInfo);
测试代码:
java
@Test
void insertRowValues() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("田七");
userInfo.setPassword("tianqi");
userInfo.setAge(16);
userInfo.setGender(0);
userInfo.setPhone("11334422");
Integer integer = userInfoXmlMapper.InsertRowValues(userInfo);
System.out.println("影响行数>:"+integer);
System.out.println("自增主键>:"+userInfo.getId());
}

4>:update:修改值
代码:
XML
<update id="UpdateByUser">
update user_info set id = 43 where username = '田七'
</update>
java
Integer UpdateByUser();
测试代码:
java
@Test
void updateByUser() {
Integer digital = userInfoXmlMapper.UpdateByUser();
System.out.println("影响行数>:"+digital);
}

5>:delete:删除记录
代码:
XML
<delete id="DeleteById">
delete from user_info where id in (#{id1},#{id2});
</delete>
java
Integer DeleteById(Integer id1,Integer id2);
测试代码:
java
@Test
void deleteById() {
Integer row = userInfoXmlMapper.DeleteById(10,43);
System.out.println("影响行数>:"+row);
}

三.小总结
1.重点理解mybatis的映射规则:把「数据库表的列」和「Java 实体类的属性」做匹配绑定,前提是名字匹配
2.不匹配可通过sql语句重命名、Results+Result(xml用resultMap+result)注解进行匹配与加配置项解决
3. 在cud中,对于xml而言是硬编码 ,无返回类型,有且唯一是影响行数 ;在注解中是软编码 ,根据方法返回类型自动进行类型转换适应匹配