这是前言。
解决端口占用问题(port is already in use)
介绍
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
使用Mybatis操作数据库,就是在Mybatis中编写SQL查询代码,发送给数据库执行,数据库执行后返回结果。
Mybatis会把数据库执行的查询结果,使用实体类封装起来(一行记录对应一个实体类对象)
配置
Mybatis操作数据库的步骤:
准备工作(创建springboot工程、数据库表user、实体类User)
引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)
编写SQL语句(注解/XML)
连接数据库的四大参数:
- MySQL驱动类
- 登录名
- 密码
- 数据库连接字符串
依赖:
1 | <dependencies> |
application.properties:
1 | #驱动类名称 |
pojo.User:
1 | public class User { |
alt
+INSERT
调用构造器
UserMapper:
1 | import com.itheima.pojo.User; |
@Mapper注解:表示是mybatis中的Mapper接口
程序运行时:框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理
@Select注解:代表的就是select查询,用于书写select查询语句
测试类代码如下:
1 |
|
运行结果:
1
2
3
4
5
6 User{id=1, name='白眉鹰王', age=55, gender=1, phone='18800000000'}
User{id=2, name='金毛狮王', age=45, gender=1, phone='18800000001'}
User{id=3, name='青翼蝠王', age=38, gender=1, phone='18800000002'}
User{id=4, name='紫衫龙王', age=42, gender=2, phone='18800000003'}
User{id=5, name='光明左使', age=37, gender=1, phone='18800000004'}
User{id=6, name='光明右使', age=48, gender=1, phone='18800000005'}
JDBC介绍
JDBC: ( Java DataBase Connectivity ),就是使用Java语言操作关系型数据库的一套API。
Mybatis框架,就是对原始的JDBC程序的封装。
数据库连接池
数据库连接池是个容器,负责分配、管理数据库连接(Connection)
- 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象
允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
- 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)
数据库连接池的好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
依赖:1
2
3
4
5
6<dependency>
<!-- Druid连接池依赖 -->
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
lombok
Lombok是一个实用的Java类库,可以通过简单的注解来简化和消除一些必须有但显得很臃肿的Java代码。
通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发、提高效率。
注解 | 作用 |
---|---|
@Getter/@Setter | 为所有的属性提供get/set方法 |
@ToString | 会给类自动生成易阅读的 toString 方法 |
@EqualsAndHashCode | 根据类所拥有的非静态字段自动重写 equals 方法和 hashCode 方法 |
@Data | 提供了更综合的生成代码功能(@Getter + @Setter + @ToString + @EqualsAndHashCode) |
@NoArgsConstructor | 为实体类生成无参的构造器方法 |
@AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有各参数的构造器方法。 |
依赖:
1 | <!-- 在springboot的父工程中,已经集成了lombok并指定了版本号,故当前引入依赖时不需要指定version --> |
在实体类上添加了@Data注解,那么这个类在编译时期,就会生成getter/setter、equals、hashcode、toString等方法。
1 | import lombok.Data; |
日志输入
1 | #指定mybatis输出日志的位置, 输出控制台 |
还可以通过某个注解,使用log.xx来写日志
预编译SQL
预编译SQL有两个优势:
- 性能更高
- 更安全(防止SQL注入)
SQL注入
SQL注入:是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。
由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。
案列: 在存在sql注入的登录界面将密码填为' or '1' = '1
,可以登陆成功
相当于select count(*) from emp where username = 'xxx' and password = '' or '1' = '1'
永远大于1,因此满足登录条件
使用预编译时:
把整个
' or '1'='1
作为一个完整的参数,赋值给第2个问号(' or '1'='1
进行了转义,只当做字符串使用)因此解决了注入问题
参数占位符
在Mybatis中提供的参数占位符有两种:${…} 、#{…}
{…}
- 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
- 使用时机:参数传递,都使用#{…}
${…}
- 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
- 使用时机:如果对表名、列表进行动态设置时使用
注意事项:在项目开发中,建议使用#{…},生成预编译SQL,防止SQL注入安全。
基础操作
删除
Mybatis框架让程序员更关注于SQL语句
- 接口方法
1 |
|
@Delete注解:用于编写delete操作的SQL语句
如果mapper接口方法形参只有一个普通类型的参数,#{…} 里面的属性名可以随便写,如:#{id}、#{value}。但是建议保持名字一致。
测试:
1 |
|
所以流程是根据数据库里的类型创建pojo类(成员名字应该和数据库字段名字相同?),(好像不用相同?那第一个程序里也不用相同?)
然后设置mapper类,此类用于查询,并用pojo类接收查询到的数据
最后在test里从ioc中得到mapper的实例化对象,然后拿这个对象里的东西/调用对象里的方法。
新增
SQL语句:
1 | insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values ('songyuanqiao','宋远桥',1,'1.jpg',2,'2012-10-09',2,'2022-10-01 10:00:00','2022-10-01 10:00:00'); |
接口方法:
1 |
|
说明:#{…} 里面写的名称是对象的属性名
测试类:
1 |
|
主键返回
概念:在数据添加成功后,需要获取插入数据库数据的主键。
默认情况下,执行插入操作时,是不会主键值返回的。如果我们想要拿到主键值,需要在Mapper接口中的方法上添加一个Options注解,并在注解中指定属性useGeneratedKeys=true和keyProperty=”实体类属性名”
1 | @Mapper |
更新
接口方法:
1 |
|
查询
接口方法:
1 |
|
数据封装
- 实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装。
如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。
解决方案:
- 起别名
- 结果映射
- 开启驼峰命名
起别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样
1 |
|
手动结果映射:通过 @Results及@Result 进行手动结果映射
1 |
|
开启驼峰命名(推荐):如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射
驼峰命名规则: abc_xyz => abcXyz
- 表中字段名:abc_xyz
- 类中属性名:abcXyz
1 | # 在application.properties中添加: |
要使用驼峰命名前提是 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名。
条件查询
- 方式一
1 |
|
以上方式注意事项:
方法中的形参名和SQL语句中的参数占位符名保持一致
模糊查询使用${…}进行字符串拼接,这种方式呢,由于是字符串拼接,并不是预编译的形式,所以效率不高、且存在sql注入风险。
- 方式二(解决SQL注入风险)
- 使用MySQL提供的字符串拼接函数:concat(‘%’ , ‘关键字’ , ‘%’)
1 |
|
在上面我们所编写的条件查询功能中,我们需要保证接口中方法的形参名和SQL语句中的参数占位符名相同。
Short name
&#{name}
Mybatis的XML配置文件
使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。
配置
创建XML映射文件
XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件 和Mapper接口放置在相同包下(同包同名)
编写XML映射文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<mapper namespace="org.example.mybatisquickstart.mapper.EmpMapper">
<!-- namespace属性为Mapper接口全限定名 -->
<!--查询操作-->
<select id="list" resultType="org.example.mybatisquickstart.pojo.Emp">
select * from emp
where name like concat('%',#{name},'%')
and gender = #{gender}
and entrydate between #{begin} and #{end}
order by update_time desc
</select>
</mapper>1
2
3
4
5
6
7
8
9
public interface EmpMapper {
/*@Select("select * from emp " +
"where name like '%${name}%' " +
"and gender = #{gender} " +
"and entrydate between #{begin} and #{end} " +
"order by update_time desc")*/
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
}- XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致
MybatisX
MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生。
野生的黑色黎博利出现了!
Mybatis动态SQL
if
<if>
:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。
1 | <if test="条件表达式"> |
- 原有的SQL语句
1 | <select id="list" resultType="org.example.mybatisquickstart.pojo.Emp"> |
- 动态SQL语句
1 | <select id="list" resultType="org.example.mybatisquickstart.pojo.Emp"> |
<where>
只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR
<set>
:动态的在SQL语句中插入set关键字,并会删掉额外的逗号。(用于update语句中)
1 | <!--更新操作--> |
foreach
SQL语句:
1 | delete from emp where id in (1,2,3); |
Mapper接口:
1 |
|
XML映射文件:
- 使用
<foreach>
遍历deleteByIds方法中传递的参数ids集合
1 | <foreach collection="集合名称" item="集合遍历出来的元素/项" separator="每一次遍历使用的分隔符" |
1 |
|
sql&include
在xml映射文件中配置的SQL,有时可能会存在很多重复的片段,此时就会存在很多冗余的代码
我们可以对重复的代码片段进行抽取,将其通过<sql>
标签封装到一个SQL片段,然后再通过<include>
标签进行引用。
<sql>
:定义可重用的SQL片段<include>
:通过属性refid,指定包含的SQL片段
SQL片段: 抽取重复的代码
1 | <sql id="commonSelect"> |
然后通过<include>
标签在原来抽取的地方进行引用。操作如下:
1 | <select id="list" resultType="org.example.mybatisquickstart.pojo.Emp"> |