文章目录
提示:以下是本篇文章正文内容,Java系列学习将会持续更新
一、为何学习 MyBatis
1-1 JDBC 操作流程
这是因为 JDBC 的操作太繁琐了,我们回顾一下 JDBC 的操作流程:
- 创建数据库连接池
DataSource
- 通过 DataSource 获取数据库连接
Connection
- 编写要执行带
?
占位符的 SQL 语句 - 通过 Connection 及 SQL 创建操作命令对象
Statement
- 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值
- 使用 Statement 执行 SQL 语句
- 查询操作:返回结果集
ResultSet
,更新操作:返回更新的数量 - 处理结果集
- 释放资源
所以需要引入一些框架进行 JDBC 优化,它可以帮助我们更方便、更快速的操作数据库。
1-2 JDBC 优化方式
Java中对JDBC优化的主要思路:
-
ORM (Object Relational Mapping) —— 核心思路, 尝试把一张表中的一条条记录完全映射成一个个的对象——去掉 SQL。当表结构 + SQL查询真的做简单映射时,非常方便。
但如果有复杂查询(一次涉及多表或者表的优化比较特殊时),就不好了 -
仅仅简化SQL的编写
常见框架 | 模式 |
---|---|
Hibernate 框架 | 偏向简化SQL的模式 |
MyBatis 框架 | 偏向ORM的模式 国内使用MyBatis相对较多(MyBatisPlus 做SQL生成) |
Spring内部提供的JdbcTemplate | 偏向简化SQL的模式 |
JPA | 完全倒向了ORM的形式,建表的过程都被抽象,我们看到的只有类 (我写了类,框架根据类建表) |
1-3 认识 MyBatis
- MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
- MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- MyBatis 可以通过简单的
XML 或注解
来配置和映射原始类型、接口和 Java POJO(普通老式 Java对象)为数据库中的记录。
简单来说 MyBatis 是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库工具。
怎么学 MyBatis:
- 配置 MyBatis 开发环境;
- 使用 MyBatis 模式和语法操作数据库。
二、使用 MyBatis
MyBatis 也是一个 ORM 框架,即对象关系映射。在面向对象编程语言中,将关系型数据库中的数据与对象建立起映射关系,进而自动的完成数据与对象的互相转换:
- 将输入数据(即传入对象)+SQL 映射成原生 SQL
- 将结果集映射为返回对象,即输出对象
ORM 把数据库映射为对象:
- 数据库表(table)–> 类(class)
- 记录(record,行数据)–> 对象(object)
- 字段(field)–> 对象的属性(attribute)
一般的 ORM 框架,会将数据库模型的每张表都映射为一个 Java 类。
Mybatis的使用有两种方式:
- 通过注解使用(相对比较容易, 好上手。做一些复杂操作的时候不太灵活)
- 通过XML配置文件的形式(比较规则,缺点就是XML 一大堆,又没有语法检查,出错不容易排查)
2-1 添加依赖
需要导入3个依赖:
- Spring Data JDBC: 这个依赖把 DataSource 对象注册到Spring中(默认HakiraDataSource),Aliyun开源Durid (国内用Durid的比较多)。
- MySQL Driver: (无论是Durid or Hakira 最终依赖MySQL官方提供的DataSource)
- MyBatis Framework: (引入了 Mybatis + MybatisSpring)
<!-- Spring Data JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis Framework -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
2-2 yml 配置连接字符串
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/lianxi?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
2-3 使用 @Mapper 注解
2-3-1 添加实体类
// 表示数据库中直接读取出来的对象
@Data
public class UserDO {
private Integer uid;
private String username;
private String password;
}
2-3-2 添加 mapper 接口
@Repository // 注册到 Spring
@Mapper // 让 mybatis 将这个接口看出一个 Mapper,并且使用代理对象代理它
public interface UserMapper { // 按照 Mybatis 的习惯,称为 UserMapper,或者习惯叫 UserDao / UserRepo
// #{username} 会对应 @Param("username") username
// #{password} 会对应 @Param("password") password
@Select("select uid, username, password from users where username = #{username} and password = #{password}")
User selectOneByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
// 由于用不到这个返回值,所以写成 void 更常见
// #{username} 会对应 userDO.getUsername() 或者 userDO.username
// #{password} 会对应 userDO.getPassword() 或者 userDO.password
@Insert("insert into users (username, password) values (#{username}, #{password})")
void insert(UserDO userDO);
// 通过 @Options 注解,添加一些配置,得到自增主键,设置成 uid
// keyProperty: 对象的属性名是 uid, keyColumn: 表的字段名的 uid
@Insert("insert into users (username, password) values (#{username}, #{password})")
@Options(useGeneratedKeys = true, keyProperty = "uid", keyColumn = "uid")
void insert2(UserDO userDO);
@Update("update users set username = #{username}, password = #{password} where uid = #{uid}")
int update(UserDO userDO);
@Delete("delete from users where uid = #{uid}")
int delete(@Param("uid") int i);
}
2-3-3 进行 Service 业务
@Service
public class UserService {
// 依赖注入
private final UserMapper userMapper;
@Autowired
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
// 注册
public User register(String username, String password) {
User user = new User(username, password);
userMapper.insert(user);
return user;
}
// 登录
public User login(String username, String password) {
return userMapper.selectOneByUsernameAndPassword(username, password);
}
}
2-4 使用 XML 配置文件
2-4-1 实体类
正常情况下,我们的实体类的属性名和数据库中字段名应该一样。如果出现以下情况,就只能使用 XML文件了。
@Data
public class User {
public Integer a;
public String b;
public String c;
public User(String username, String password) {
this.b = username;
this.c = password;
}
}
2-4-2 UserMapper 接口
// xml 中需要指定 Mapper 接口的位置
@Mapper
@Repository
public interface UserMapper {
User selectOneByUid(@Param("uid") int uid);
List<User> selectListByUidList(@Param("uidList") List<Integer> uidList);
int insertBatch(@Param("userList") List<User> userList);
User selectByUser(@Param("user") User user);
}
2-4-3 创建 mapper.xml
在 resources/mapper 下创建 mapper.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 接口 -->
<mapper namespace="com.example.mybatis_xml.UserMapper">
<!-- 映射到 User 实体类 -->
<resultMap id="xxx" type="com.example.mybatis_xml.User">
<!-- id property="属性名" javaType="属性类型" column="字段名" jdbcType="字段类型" / -->
<id property="a" javaType="Integer" column="uid" jdbcType="INTEGER" />
<result property="b" javaType="String" column="username" jdbcType="VARCHAR" />
<result property="c" column="password" />
</resultMap>
<!-- id="mapper中的方法名" parameterType="参数类型" -->
<select id="selectOneByUid" resultMap="xxx" parameterType="int">
select uid, username, password from users where uid = #{uid}
</select>
<select id="selectListByUidList" resultMap="xxx" parameterType="List">
select uid, username, password from users where uid in (
<!-- for (id : uidList) { -->
<foreach collection="uidList" item="id" separator=", ">
#{id}
</foreach>
) order by uid
</select>
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="a" keyColumn="uid">
insert into users (username, password) values
<foreach collection="userList" item="user" separator=", ">
(#{user.b}, #{user.c})
</foreach>
</insert>
<select id="selectByUser" resultMap="xxx" parameterType="com.peixinchen.mybatis_xml.User">
select uid, username, password from users where
<if test="user.a != null">
uid = #{user.a}
</if>
<if test="user.b != null">
and username = #{user.b}
</if>
<if test="user.c != null">
and password = #{user.c}
</if>
</select>
</mapper>
2-4-4 在 yml 中声明 mapper.xml 的路径
mybatis:
mapper-locations: classpath:mapper/**.xml
三、参数占位符 #{} 和 ${}
#{}
:预编译处理。会帮我们加 引号 处理,防止SQL注入。
${}
:字符直接替换。在某些特定的场景使用。
#{} 传递字符串类型的字段:
@Select("select username from users where username = #{username}")
User select(@Param("username") String username);
// select username from users where username = "wangshaoyu"; // √
@Select("select username from users where username = ${username}")
User select(@Param("username") String username);
// select username from users where username = wangshaoyu; // ×
${} 传递整型的字段:
@Select("select * from users where username = #{username} offset ${offset} limit ${limit}")
void sort(@Param("username") String username,
@Param("offset") int a,
@Param("limit") int b);
// select * from users where username = "wangshaoyu" offset 5 limit 3;
like 查询:
错误用法:使用 #{} 报错
select * from userinfo where username like '%#{username}%';
// 相当于 select * from userinfo where username like '%'username'%'; // ×
正确用法:使用 #{} + mysql 的内置函数 concat()
select * from userinfo where username like concat('%',#{username},'%');
// 相当于 select * from userinfo where username like '%username%'; // √
总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是MyBatis的学习,认识到MyBatis带给我们的便利,更简单的去操作数据库,MyBatis的两种使用方式:注解 / XML配置文件。之后的学习内容将持续更新!!!