目录
MyBatis简介
MyBatis的准备工作
框架的添加
连接数据库字符串的配置
MyBatis中XML路径的配置
编辑 MyBatis的使用
各层的实现
进行数据库操作
增加操作
拓展
修改操作
删除操作
查询操作
结果映射
单表查询
多表查询
like模糊查询
动态SQL
/
MyBatis简介
MyBatis是基于JDBC的一个工具框架,能够更好帮助程序与数据库进行交互,也能更方便的进行数据库中数据的存储与读取.
MyBatis是一个ORM(Object Relational Mapping)框架,ORM即是对象关系映射.在编程语言中,将关系型数据库中的数据与对象建立映射关系,更方便的完成数据与对象间的转换.
一般的ORM映射关系:
在加入了Mybatis的项目中,一般会为一张表创建一个类并进行映射,就使得像平常操作对象一般操作数据库中的数据.
MyBatis的准备工作
框架的添加
在项目中添加Mysql数据库与MyBatis相关的框架.
如果是老的项目可以使用EditStarters插件进行添加
连接数据库字符串的配置
在项目的配置文件中对数据库的连接进行配置,此处使用的是yml类型的配置文件.主要是作用是将项目与数据库能够进行连接.
记得对URL中的目标数据库进行修改.
spring:datasource:url: jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&useSSL=false #连接数据库的地址username: root #数据库的用户名password: #数据库的密码driver-class-name: com.mysql.cj.jdbc.Driver
将上述代码放置到yml配置文件中
注意事项 :
检查mysql-connector-java的版本号,如果是 5.x 之前的使⽤的“com.mysql.jdbc.Driver”,如果是⼤于 5.x使⽤的是“com.mysql.cj.jdbc.Driver”
MyBatis中XML路径的配置
在resources的目录下创建一个目录(此处我命名为mybatis).
并在项目的配置文件中将刚刚创建的目录添加到mybatis的xml路径
最终配置文件大致为:
MyBatis的使用
一般的业务的后端开发思路为:
我们只要跟着上面的开发思路来写代码就好了.
注意:
下面所创建的所有类都要跟启动类放到同一个文件夹之中.
各层的实现
创建实体类
映射到一个数据库中的表.
@Data
public class User {private String name;private int age;private int id;private String sex;
}
创建Serveric类
@Service
public class UserService {@AutowiredUserMapper userMapper;public User getUserByName(String name){return userMapper.getUserByName(name);}
}
创建Controller类
@Controller
public class UserController{@AutowiredUserService userService;public User getUserByName(String name){return userService.getUserByName(name);}
}
创建Mapper
Mapper的组成为接口+XML
@Mapper
public interface UserMapper {User getUserByName(@Param("name") String name);//使用Param注解,将接口方法中的参数设置成为xml中传输的参数(不写也可以,写了更严谨可以尽量避免出现bug)
}
在之前的配置文件中配置mybatis的xml的目录中创建一个对应的xml
(将下面的代码拷贝,更改对应的mapper标签中的namespace.在mapper标签中写上对应的sql语句)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybati
s.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.UserMapper"><!-- sql语句的实现-->
</mapper>
mapper标签中需要指定namespace属性,表示命名空间,为mapper接口的全限定名(包名+类名)去指定一个mapper.
进行数据库操作
对应表的创建语句:
create table Users(name varchar(15),age int,id int primary key auto_increment,sex varchar(6));
在MyBatis中的SQL语句都在XML文件中搭配对应的标签来实现.
可以在SpringBoot项目的配置文件中设置Mapper类的日志等级为debug,这样就可以在控制台中查看数据库操作的预处理语句,参数和受影响的行数了.
(此处为yml类型配置文件的语句)
logging:level:com.example.demo.Mapper: debug //此处是类的路径 + 日志的等级
增加操作
增加操作使用<insert>标签实现
controller类
@ResponseBody//记得添上@ResponseBody,表明返回的是一个数据而不是页面@PostMapping("/add")//POST由客户端上传数据至服务器public Integer add(@RequestBody User user){//@RequestBody标签将方法中的user参数获取请求body中的json格式return userService.add(user);}
Service类
public Integer add(User user){return userMapper.add(user);}
Mapper
最好要使用Integer做返回值噢
//增加操作,返回受影响的行数//返回类型为Integer而不是int,是因为int的默认值为0,Integer的默认值为null//使用int就不知道语句是否对数据库造成了影响,//Integer可以区分未赋值与受影响行数为0的区别Integer add(User user);
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybati
s.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.UserMapper"><!--sql语句的实现--><insert id="add">insert into Users(name,age,sex) values(#{name},#{age},#{sex});<!--#{}中为对象的属性--></insert>
</mapper>
可以看到返回值为受影响的行数.
拓展
返回受影响的行数据的主键
当我们在某些情况下想要获取对应的主键,可以在insert标签上进行设置.
useGeneratedKeys : 使用主键,默认值为false,
keyProperty : 主键的属性名为(实体类中的属性)
<insert id="add" useGeneratedKeys="true" keyProperty="id">insert into Users(name,age,sex) values(#{name},#{age},#{sex});<!--#{}中为对象的属性-->
</insert>
然后我们就可以直接在方法中使用对象的主键属性了,先前都是默认自增值没有对其进行赋值,
@ResponseBody//记得添上@ResponseBody,表明返回的是一个数据而不是页面@PostMapping("/add")//POST由客户端上传数据至服务器public Integer add(@RequestBody User user){//@RequestBody标签将方法中的user参数获取请求body中的json格式Integer ret = userService.add(user);System.out.println("UserID为:" + user.getId());return ret;}
修改操作
使用<update>标签
由于Controller类与Service类都大差不大就不展示啦.
Mapper
Integer update(User user);
<update id="update">update Users set age = #{age} where name = #{name};
</update>
删除操作
删除操作使用<delete>标签
Mapper
Integer delete(User user);
<delete id="delete">delete from Users where id = #{id};
</delete>
查询操作
结果映射
在上述的增加,删除以及修改操作中,一般的默认的返回值为受影响的行数.但其实可以不使用映射来接收这个参数的.
但对于查询操作来说,不得不接收返回的参数,不然会进行报错.
而在MyBatis中,实现结果映射的标签一共有两种<resultType>返回类型与<resultMap>返回字典映射
<resultType>返回类型
此标签能够适用于绝大多数的场景,其中resultType表明要返回的类型.
可以是一个类,也可以的基本类型或引用类型.
其中的resultType值可以为类名,或"string"或"java.lang.String"或"int"或"java.lang.Integer"...
<select id="getNameById" resultType="java.lang.String">select name from Users where id = #{id};
</select>
因为<resultMap>标签的使用比较麻烦也以及不常用了,就不再此处介绍了
单表查询
将Controller类的标签更改为get方法,并使用表单传输信息.
User getNameById(@Param("id") Integer id);
<select id="getNameById" resultType="com.example.demo.model.User">select name from Users where id = #{id};
</select>
多表查询
like模糊查询
因为使用#{}会进行预处理编译,会把数据自动的加上单引号 zhangsan -> 'zhangsan'
如果直接使用模糊查询, like '%#{name}%' 就会变成 -> like '%'name'%' 显然是错误的,但如果使用${}字符串替换又会有sql注入的风险,
所以我们可以使用concat方法对%与参数进行连接.
<select id="getByName" resultType="com.example.demo.model.User">select * from Users where name like concat('%',#{name},'%');
</select>
动态SQL
<if>
我们之前可能在遇到过,填写个人信息表单的时候会出现非必填项.
此处就可以使用<if>标签来实现非必填项的方式
当我们填写name,age却不想写填写sex的时候,就可以使用<if>标签来拼接SQL语句
Mapper:
Integer add2(User user);
XML:
<insert id="add2">insert into Users(name,age<if test="sex != null">,sex</if>) values(#{name},#{age}<if test="sex != null">,#{sex}</if>);</insert>
其中<if>标签中的test属性填写的是传输参数的判断语句,sex是user对象的属性并非数据库中的字段.
如果传输的user对象中sex属性为空,则不填写<if>标签中的字符.
对应的,因为<if>标签的作用,预处理后的语句也没有出现sex字段
<trim>
上面的例子为单个非必填选项,那如果我每一个都是非必填呢?
因为SQL语句中字段间的分隔需要逗号来实现,所以单单依靠于<if>标签来实现是不可行的,这时候就出现了另一种标签:<trim>
<trim>标签与<if>标签搭配使用适用于多个字段都是非必填的场景.
<trim>标签中有如下属性:
- prefix:表示整个语句块,以prefix的值作为前缀
- suffix:表示整个语句块,以suffix的值作为后缀
- prefixOverrides:表示整个语句块要去除掉的前缀
- suffixOverrides:表示整个语句块要去除掉的后缀
<insert id="add2">insert into Users<trim prefix="(" suffix=")" suffixOverrides=","><if test="name != null">name,</if><if test="age != null">age,</if><if test="sex != null">sex,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="name != null">#{name},</if><if test="age != null">#{age},</if><if test="sex != null">#{sex},</if></trim></insert>
在使用<trim>标签之后可传输的数据就会变得很灵活了
<where>/<set>
其中还有这两个标签,其实这两个标签都是<trim>的变形
<set>也是同样的,只是<set>等价于<trim prefix="set" suffixOverrides=",">
<foreach>
对集合进⾏遍历时可以使⽤该标签。<foreach>标签有如下属性:
- collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
- item:遍历时的每⼀个对象
- open:语句块开头的字符串
- close:语句块结束的字符串
- separator:每次遍历之间间隔的字符串
<delete id="deleteByIds">delete from articlewhere id in<foreach collection="list" item="item" open="(" close=")" separator=",">#{item}</foreach>
</delete>
就像java里的foreach遍历一样.
传输数组进行调试
预处理后的样子: