MyBatis入门
MyBatis入门
MyBatis 是什么?
-
MyBatis 是?款优秀的持久层框架,它?持?定义 SQL、存储过程以及?级映射。
- 对象关系映射框架
- 存储过程
- 封装了一堆sql的方法
- 缺点:
- 操作难度大
- 没办法调试
- 修改和扩展难
- 逻辑判断放在了 MySQL服务器,浪费数据库资源
- ?级映射
- 表字段和类字段 的 映射
- MyBatis 去除了?乎所有的 JDBC 代码以及设置参数和获取结果集的?作。
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接?和 Java POJO(Plain Old Java Objects,普通?式 Java 对象)为数据库中的记录。
-
简单来说 MyBatis 是更简单完成程序和数据库交互的?具,也就是更简单的操作和读取数据库?具
-
MyBatis 在整个框架中的定位,框架交互流程图:
-
-
为什么要实现 InterFace ,而不直接实现类:
- 通过 xml解耦 Java 和 数据库的关系
-
原理:
- 通过代理对象实现 接口,生成 SQL 调用 JDBC
-
-
-
MyBatis 也是?个 ORM 框架,ORM(Object Relational Mapping),即对象关系映射。
-
在?向对象编程语?中,将关系型数据库中的数据与对象建?起映射关系
-
进??动的完成数据与对象的互相转换:
- 将输?数据(即传?对象)+SQL 映射成原? SQL
- 将结果集映射为返回对象,即输出对象
-
ORM 把数据库映射为对象:
- 数据库表(table)–> 类(class)
- 记录(record,?数据)–> 对象(object)
- 字段(field) --> 对象的属性(attribute)
-
-
?般的 ORM 框架,会将数据库模型的每张表都映射为?个 Java 类。
-
也就是说使? MyBatis 可以像操作对象?样来操作数据库中的表,可以实现对象和数据库表之间的转换
-
为什么要学习 MyBatis?
-
那已经有了 JDBC 了,为什么还要学习 MyBatis?
- JDBC 的操作流程:
- 创建数据库连接池 DataSource
- 通过 DataSource 获取数据库连接 Connection
- 编写要执?带 ? 占位符的 SQL 语句
- 通过 Connection 及 SQL 创建操作命令对象 Statement
- 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值
- 使? Statement 执? SQL 语句
- 查询操作:返回结果集 ResultSet,更新操作:返回更新的数量
- 处理结果集
- 释放资源
- JDBC 的操作流程:
-
从上述代码和操作流程可以看出,对于 JDBC 来说,整个操作?常的繁琐
- 我们不但要拼接每?个参数,?且还要按照模板代码的?式,?步步的操作数据库
- 并且在每次操作完,还要?动关闭连接等,?所有的这些操作步骤都需要在每个?法中重复书写。
-
MyBatis 可以帮助我们更?便、更快速的操作数据库
入门
环境配置
1.添加依赖
2.配置数据库链接信息
-
application.yml
-
spring: datasource: url: jdbc:mysql://localhost:3306/mycnblog username: root password: 200337qqq driver-class-name: com.mysql.cj.jdbc.Driver
- 注意事项
- 如果使? mysql-connector-java 是 5.x 之前的使?的是“com.mysql.jdbc.Driver”,如果是?于 5.x使?的是“com.mysql.cj.jdbc.Driver”。
- 注意事项
-
3.配置 MyBatis 中的 XML 路径
-
MyBatis 的 XML 中保存是查询数据库的具体操作 SQL,配置如下:
-
# 配置 mybatis xml 的?件路径,在 resources/mapper 创建所有表的 xml ?件 mybatis: mapper-locations: classpath:mapper/**Mapper.xml
-
添加业务代码
-
mybatis 组成 2 部分:
- 接口 (表的所有操作方法)
- 给其他类调用
- XML实现接口
- 具体sql的实现
- 接口 (表的所有操作方法)
-
按照后端开发的?程思路,也就是下?的流程来实现 MyBatis 查询所有?户的功能:
添加实体类
-
先添加?户的实体类:
-
import lombok.Data; import java.util.Date; @Data public class Userinfo { private Integer id; private String username; private String password; private String photo; private Date createTime; private Date updateTime; }
-
添加 mapper 接?
-
数据持久层的接?定义:
-
@Mapper public interface UserinfoMapper { List<Userinfo> getAll(Integer id); }
-
添加 UserinfoMapper.xml
-
数据持久成的实现,mybatis 的固定 xml 格式:
-
namespace
- 要实现接口的全路径
-
id
- 实现的方法名
-
resultType
- 返回类型
-
${id}
- 动态标签,用于传入参数
-
<?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.mybatistest.mapper.UserinfoMapper"> <select id="getAll" resultType="com.example.mybatistest.entity.Userinfo"> select * from userinfo where id =${id} </select> </mapper>
-
添加 Service
@Service
public class MybatisServiceImp implements MybatisService {
@Autowired
private UserinfoMapper userinfoMapper;
@Override
public List<Userinfo> getAll(Integer id) {
return userinfoMapper.getAll(id);
}
}
添加 Controller
-
控制器层的实现代码如下:
-
@RestController @RequestMapping("/user") public class MybatisController { @Autowired MybatisService mybatisService; @RequestMapping("/getuser") //因为Windows不区分大小写,所以尽量使用 小写 ,替代:中划线 get-user public List<Userinfo> getuser(Integer id){ if(id == null){ return null; } return mybatisService.getAll(id); } }
-
使? apipost 测试
注意事项
返回值为 list的时候,填 list中的类型
-
List<Userinfo> getAll();
-
<select id="getAll" resultType="com.example.mybatis3.entity.Userinfo"> select * from userinfo </select>
-
简单的CURD操作
插入
-
步骤:
-
在mapper中声明方法
-
传递的是对象
-
int add(Userinfo userinfo);
-
-
-
在 mapper.xml 中 提供 sql实现
-
赋值的是对象属性
- 注意: 对应的不是数据库字段,而是 实体类的属性
-
<insert id="add" > insert into userinfo(username, password, createtime, updatetime) values(#{username},#{password},#{createTime},#{updateTime}) </insert>
- 默认是返回int 受影响的行数, 不会有 resultType
-
-
-
如何拿到 插入实体类对应的 id
-
<insert id="add" useGeneratedKeys="true" keyProperty="id"> insert into userinfo(username, password, createtime, updatetime) values(#{username},#{password},#{createTime},#{updateTime}) </insert>
- useGeneratedKeys:
- 这会令 MyBatis 使? JDBC 的 getGeneratedKeys ?法来取出由数据库内部?成的主键
- ?如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的?动递增字段),默认值:false。
- 这会令 MyBatis 使? JDBC 的 getGeneratedKeys ?法来取出由数据库内部?成的主键
- keyColumn:
- 设置?成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第?列的时候,是必须设置的。
- 如果?成列不??个,可以?逗号分隔多个属性名称。
- keyProperty:
- 指定对应 实体类中的 属性名称
- 指定能够唯?识别对象的属性,MyBatis 会使? getGeneratedKeys 的返回值或 insert 语句的 selectKey ?元素设置它的值
- 默认值:未设置(unset)。如果?成列不??个,可以?逗号分隔多个属性名称
- useGeneratedKeys:
-
测试:
-
修改
-
int upUser(Userinfo userinfo);
-
<update id="upUser"> update userinfo set username=#{username} where id = #{id} </update>
删除
-
int deleteUser(Integer id);
-
<delete id="deleteUser"> delete from userinfo where id=#{id} </delete>
查询
参数占位符 #{} 和 ${}
- #{}:预编译处理
- ${}:字符直接替换
- 预编译处理是指:
- MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号
- 使? PreparedStatement的 set ?法来赋值。
- 直接替换:
- 是MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。
- 预编译处理是指:
${} 优点
- 使? ${sort} 可以实现排序查询,?使? #{sort} 就不能实现排序查询了
- 因为当使? #{sort} 查询时
- 如果传递的值为 String 则会加单引号,就会导致 sql 错误。
SQL 注?问题
- 使用 #{} 占位符会告诉 mysql这是 一个值,而不是关键字等其他信息,所以不会出现sql注入的问题
<select id="isLogin" resultType="com.example.demo.model.User">
select * from userinfo where username='${name}' and password='${pwd}'
</select>
- sql 注?代码:“’ or 1='1”
-
结论:?于查询的字段,尽量使? #{} 预查询的?式
-
#{} 当作预处理,填充到 原来的value上
-
预查询:
- 只是一个值的替换,本身的查询规则,查询选择(索引)都定了
- 只是在某一个零件上用一个动态的value替换的
- 相当于模板
-
like 查询
-
like 使? #{} 报错
-
<select id="findUserByName2" resultType="com.example.demo.model.User"> select * from userinfo where username like '%#{username}%'; </select>
- 相当于: select * from userinfo where username like ‘%‘username’%’;
-
-
这个是不能直接使? ${}
- 因为 username不能穷举,会有 sql注入的问题
-
可以考虑使? mysql 的内置函数 concat() 来处理,实现代码如下:
-
将 username,% 拼接起来
-
<select id="findUserByName3" resultType="com.example.demo.model.User"> select * from userinfo where username like concat('%',#{username},'%'); </select>
-
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!