前言
通过本篇博客,我们将学到以下内容
1.使⽤MyBatis完成简单的增删改查操作,参数传递
2.掌握MyBatis的两种写法: 注解和 XML⽅式
3.掌握 MyBatis 相关的⽇志配置
什么是 MyBatis?
MyBatis是⼀款优秀的 持久层 框架,⽤于简化JDBC(关于 JDBC 推荐看JAVA连接数据库 JDBC编程)的开发,通过 MyBatis 我们可以很简单的访问和操作数据库
MyBatis 使用流程
准备工作
配置都是放到 application.properties 或者 application.yml 文件中
1.创建项目,引入依赖
本篇博客使用 MyBatis 框架的是 springboot ⼯程,所以我们先要创建 springboot 项目,推荐看idea必装的插件 Spring Boot Helper 插件(创建 Spring Boot 项目),并导⼊ mybatis 的依赖、mysql 的驱动包
如果是新创建的项目,在创建时直接导入即可
如果是已经创建的项目可以通过 EditStarters 插件快速导入,推荐看idea必装插件EditStarters(快速引入依赖)
2.配置 MyBatis 连接数据库
Mybatis要连接数据库,需要配置数据库的相关参数
•MySQL驱动
•登录名
•密码
•数据库连接字符串
配置内容如下:
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库url(mybatis_test是数据库的名称)
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
#数据库用户名
spring.datasource.username=root
#数据库密码
spring.datasource.password=xxx
注意事项:如果使⽤MySQL是 5.x 之前的使⽤的是 com.mysql.jdbc.Driver,如果是⼤于 5.x 使⽤的是 com.mysql.cj.jdbc.Driver
3.配置 MyBatis 日志
通过 MyBatis 日志,我们可以很好的观察 sql 语句的执行情况,配置内容如下:
#指定mybatis输出⽇志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
4.准备测试数据
数据表 userinfo 的结构如下:
实体类的定义如下:
@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;
}
通过注解进行数据库操作
1.通过注解实现 增(insert)
@Mapper //将 UserInfoMapper 接口的实现类的对象交给 Spring 的 IoC 容器进行管理
public interface UserInfoMapper {
//1.增加用户信息
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into userinfo( username, password, age, gender, phone )"+
"values(#{username},#{password},#{age},#{gender},#{phone})")
public Integer insert(UserInfo userInfo);
}
@Mapper 注解表示将 UserInfoMapper 接口的实现类的对象交给 Spring 的 IoC 容器进行管理,我们后面可以通过 @Autowired 注解来获取到 Spring 的 IoC 容器管理的对象,推荐看Spring IoC & DI 使⽤
@Options 注解用来获得自增主键,因为我们在创建表的时候,主键 id 设置了AUTO_INCREMENT ,所以在插入数据的时候我们不需要指定 id 的值,mysql 会自动赋值,但我们插入数据以后可能需要知道插入的这条数据的自增 id 为多少,我们就可以通过@Options 注解来获取:
useGeneratedKeys = true 表示需要 MyBatis 取出表中由数据库内部⽣成的主键
keyProperty = "id" 表示 MyBatis 取出的主键数据赋值给哪个属性
@Insert 注解内写的是插入的 sql 语句,调用 insert 方法就会执行 @Insert 注解内的 sql 语句,通过 #{} 的方式传参,参数直接写 userInfo 对象的属性名,Spring 会自动进行匹配
执行 insert 方法调用 sql 语句后会返回受影响的数据行数,所以返回类型可以写为 Integer
扩展:可以通过 @Param 注解修改参数名 比如 insert(@Param("use") UserInfo userInfo),修改以后传参就要用 #{use.username} 的形式传
测试代码
我们可以通过在业务代码上右键选择 Generate->Test 编写当前类中指定方法的测试代码
如下代码 userInfoMapper 调用 insert 方法将数据插入到表中后,会将自增主键赋值给userInfo 对象的 id 属性,通过 getId 方法获得该行数据的自增主键
@SpringBootTest
class UserInfoMapperTest {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
void insert() {
UserInfo userInfo=new UserInfo();
userInfo.setUsername("zhaoliu");
userInfo.setPassword("zhaoliu");
userInfo.setGender(2);
userInfo.setAge(21);
userInfo.setPhone("18612340005");
userInfoMapper.insert(userInfo);
System.out.println(userInfo.getId());
}
}
@SpringBootTest ,在测试类中没有配置 SpringBoot 的环境,所以我们要想使用 Spring Boot 的相关机制,就要加上 @SpringBootTest 注解,引入 SpringBoot 的环境
2.通过注解实现 删(delete)
//2.通过 id 来删除数据
@Delete("delete from userinfo where id=#{id}")
public Integer delete(Integer id);
@Delete 注解内写的是删除的 sql 语句,调用 delete 方法就会执行 @Delete 注解内的 sql 语句,通过 #{} 的方式传参
执行 delete 方法调用 sql 语句后会返回受影响的数据行数,所以返回类型可以写为 delete
3.通过注解实现 改(update)
//3.通过 id 来修改 username
@Update("update userinfo set username=#{username} where id=#{id};")
public Integer update(Integer id,String username);
@Update 注解内写的是修改的 sql 语句,调用 update 方法就会执行 @Update 注解内的 sql 语句,通过 #{} 的方式传参
执行 update 方法调用 sql 语句后会返回受影响的数据行数,所以返回类型可以写为 delete
4.通过注解实现 查(select)
//通过 id 来查找用户信息
@Select("select id,username,password,age,gender,phone,delete_flag,create_time," +
"update_time from userinfo where id=#{id};")
public UserInfo select(Integer id);
开发经验:关于 select 的 sql 语句尽量不要用 * ,需要什么字段就获取什么字段,要是都需要,就把所有的字段都填上
@Select 注解内写的是查询的 sql 语句,调用 select 方法就会执行 @Select 注解内的 sql 语句,通过 #{} 的方式传参
由于我们是通过 id 来查询数据,所以只会有一行数据,就只需要一个 UserInfo 对象接收即可,所以返回值类型为 UserInfo ,如果我们查询到多条数据,返回值类型就应该是 List<UserInfo> 要是依然用 UserInfo 来接收的话程序就会报错
测试代码
void select() {
UserInfo userInfo=new UserInfo();
userInfo=userInfoMapper.select(3);
System.out.println(userInfo.toString());
}
查询到数据以后,MyBatis 会根据表的字段名和 UserInfo 对象的属性名自动建立映射关系,但此时我们的代码会出现一些问题,查询以后得到的数据如下:
如上图所示,查询到的该行数据中 delete_flag ,create_time,update_time 为null,说明这3个字段中的内容没有成功赋值给 userInfo 对象
这是因为数据表 userinfo 的字段为id,username,password,age,gender,phone,delete_flag,create_time,update_time
UserInfo 类的属性为
id,username,password,age,gender,phone,deleteFlag,,createTime,updateTime
我们可以看到 id,username,password,age,gender,phone 这几个数据表的字段名和 UserInfo 类的属性名相同,所以 MyBatis 能够知道它们之间的映射关系,而delete_flag,create_time,update_time 这几个数据表的字段名和 UserInfo 类的属性名deleteFlag,,createTime,updateTime 不相同,所以 MyBatis 不知道它们之间的映射关系,就无法把对应的数据赋值到 userInfo 对象的这3个属性中
手动设置映射关系
此时就需要我们通过 @Results 注解手动设置它们之间的映射关系,代码如下:
//通过 @Results 注解设置映射关系(当字段名和属性名不相同时才有必要设置)
// id 表示为该映射关系命名,方便其他方法也可以使用该映射关系,value 表示具体的映射关系
@Results(id = "UserInfoRes",value = {
@Result(column = "delete_flag",property = "deleteFlag"),
@Result(column = "create_time",property = "createTime"),
@Result(column = "update_time",property = "updateTime")
})
@Select("select id,username,password,age,gender,phone,delete_flag,create_time," +
"update_time from userinfo where id=#{id};")
public UserInfo select2(Integer id);
如上代码,我们通过 @Results 注解,手动设置了数据表的字段名和类的属性名之间的映射关系
id 表示为该映射关系命名,以便后面的方法可以直接使用此处定义的映射关系,value 就表示具体的映射关系,映射关系有多条,所以 value 对应的值是数组,要用 {} 包裹
通过 @Result 注解具体设置一条映射关系,column 翻译为列,表示数据表的字段名,property 翻译为属性,表示类的属性名,此时就为字段名和属性名建立了映射关系
此时我们再测试 select2 方法,如下所示:
userinfo 对象中的 deleteFlag,,createTime,updateTime 这3个属性被成功赋值
开启驼峰命名(推荐)
由于在开发中,表的字段名通常都是蛇形的方法,例如:delete_flag,create_time,update_time
而实体类属性的命名通常都是小驼峰的方法,例如:deleteFlag,,createTime,updateTime,所以 MyBatis 提供了相关的配置项,可以直接将蛇形的字段名和小驼峰的属性名建立映射关系
配置如下:
mybatis.configuration.map-underscore-to-camel-case= true
加上该配置以后,MyBatis 就知道了delete_flag,create_time,update_time 和deleteFlag,,createTime,updateTime 之间的映射关系
通过XML实现数据库操作
准备工作
1.配置 mybatis xml 的⽂件路径
,配置代码如下
mybatis.mapper-locations=classpath:mapper/**Mapper.xml
classpath 表示 resources 文件夹
mapper/**Mapper.xml 是 xml 文件在 resources 文件夹下的具体路径,按上述配置,我们的 xml 文件可以放到下图中的位置
2.MyBatis 的固定 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.springbootdemo.Mapper.UserInfoXMLMapper">
</mapper>
上面的固定格式中,<mapper> 标签的 namespace 属性,表示命名空间,值为 mapper 接⼝(我们需要创建一个 mapper 接⼝来进行方法的声明)的全限定名,包括全包名.类名
1.通过XML实现 增 (insert)
在 UserInfoXMLMappe 接口中方法的声明
@Mapper
public interface UserInfoXMLMapper {
//插入数据
Integer insert(UserInfo userInfo);
}
在 UserInfoXMLMapper.xml 文件中写方法的实现( sql 语句)
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into userinfo(username,password,age,gender,phone)
values(#{username},#{password},#{age},#{gender},#{phone});
</insert>
<insert> 标签表示定义插入的 sql 语句 其中 id 属性对应 UserInfoXMLMapper 中的方法名,通过 #{} 进行传参
如果我们需要获得插入该行数据时产生的自增主键,设置 useGeneratedKeys 为 true 表示要获取自增主键,keyProperty 属性表示获取到的自增主键赋值给对象的哪个属性
2.通过XML实现 删 (delete)
在 UserInfoXMLMappe 接口中方法的声明
//根据 id 删除数据
Integer delete(Integer id);
在 UserInfoXMLMapper.xml 文件中写方法的实现( sql 语句)
<delete id="delete">
delete from userinfo where id=#{id};
</delete>
<delete> 标签表示定义删除的 sql 语句 其中 id 属性对应 UserInfoXMLMapper 中的方法名,通过 #{} 进行传参
3.通过XML实现 改 (update)
在 UserInfoXMLMappe 接口中方法的声明
//根据 id 修改姓名
Integer update(Integer id,String username);
在 UserInfoXMLMapper.xml 文件中写方法的实现( sql 语句)
<update id="update">
update userinfo set username=#{username} where id=#{id};
</update>
<update> 标签表示定义修改的 sql 语句 其中 id 属性对应 UserInfoXMLMapper 中的方法名,通过 #{} 进行传参
4.通过XML实现 查 (delete)
在 UserInfoXMLMappe 接口中方法的声明
//查询所有的用户信息
List<UserInfo> select();
在 UserInfoXMLMapper.xml 文件中写方法的实现( sql 语句)
<select id="select" resultType="com.example.springbootdemo.dao.UserInfo">
select id,username,password,age,gender,phone,delete_flag,create_time,
</select>
但我们通过 UserInfoXMLMappe 接口的实现类对象调用 select 方法我们同样会发现,出现了deleteFlag,createTime, updateTime,三个属性为 null ,没有赋值的问题
这个问题的出现同样是因为,字段名和属性名不同,导致 MyBatis 不知道它们之间的映射关系,解决方法也和通过注解进行数据库操作差不多,其中开启驼峰命名这个方法是完全相同的,手动设置映射关系有点不同
手动设置映射关系
通过 xml 文件操作数据库时,手动设置映射关系的代码如下:
<resultMap id="UseMap" type="com.example.springbootdemo.dao.UserInfo">
<id column="id" property="id"></id>
<result column="delete_flag" property="deleteFlag"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</resultMap>
<resultMap> 在该标签中设置映射关系,id 属性表示为该映射关系命名,方便后续重复使用,type 属性表示映射关系对应的类的全限定名,包括全包名.类名
<id> 标签表示设置主键的映射关系,column 属性对应字段名,property 属性对应属性名
<result> 标签表示设置普通的映射关系 ,column 属性对应字段名,property 属性对应属性名
设置好映射关系后,要将映射关系添加到代码实现中
<select id="select" resultMap="UseMap">
select id,username,password,age,gender,phone,delete_flag,create_time,
update_time from userinfo;
</select>
如上图,通过 resultMap 属性,添加映射关系到具体代码实现中