文章目录
Mybatis 是一款优秀的 持久层 框架,用于简化JDBC的开发
入门
使用Mybatis查询所有用户数据
1.创建工程
(1)引入Mybitis的相关依赖,配置Mybatis(数据库连接信息)
(2)选择如下图这两项依赖
2.准备工作(创建springboot工程,数据库表user,实体类User)
(1)先创建数据库mybatis
(2)在main.resources下配置数据库的连接信息
只需修改数据库名,用户名和密码
(3)在mian下建立pojo,用于存储实体类。然后再此下面创建java类User.
封装User类下的属性,编写get 、set、toString方法,有参构造与无参构造
3.编写SQL语句(注解/XML)
(1)在pojo同层级目录下创建mapper,再创建UserMapper接口。在里边编写SQL语句。
在UserMapper接口中,有一个名为list的方法,这个方法被标记了一个@Select注解,@Select注解的值是"select * from user",这意味着list方法将执行这个SQL语句来获取所有用户的信息。
list方法的返回类型是
List<User>
,这表示它将返回一个User对象的列表,其中每个User对象都对应于数据库中的一条记录。User类是一个与user表对应的Java实体类,其中包含了与表中的列相对应的属性。
4.test下编写测试代码
第16,17行:使用Spring的
@Autowired
注解来自动注入UserMapper的实例。
第20行:调用userMapper的list
方法来获取数据库中所有用户的列表。这个方法应该返回一个User对象的List。
第21,22行:使用Java 8的流(Stream)和lambda表达式来遍历userList中的每个User对象,并在控制台上打印它们。
JDBC
使用java语言操作关系型数据库的一套规范,即接口
各个数据库厂商去实现这套接口,提供数据库驱动jar包,即数据库的驱动
数据库连接池
标准接口:DataSource
获取连接:Connection getConnection() throws SQLException;
lombok
Lombok是一个实用的Java类库,能通过注解的形式自动生成构造器,getter/setter、equals、hashcode等方法,并自动生成日志变量,简化Java开发。
注解 | 作用 |
---|---|
@Getter/@Setter | 为所有属性提供get/set方法 |
@ToString | 会给类自动生成易阅读的toString方法 |
@EqualAndHashCode | 根据类所拥有的非静态字段自动重写equals方法和hashCode方法 |
@Data | 提供了更综合的生成代码功能(@Getter+@Setter+@ToString+@EqualAndHashCode) |
@NoArgsConstructor | 为实体类生成无参构造方法 |
@AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有个参数的构造方法 |
添加lombok:在pom.xml中的<dependcies>
中添加如下代码:
添加后要按一下右上方的Maven按钮。
使用lombk之前的类定义:
使用lombok之后的类定义:
节省许多get、set语句
基础操作
删除
根据主键删除
SQL语句:delete from emp where id=17;
接口方法:
@Delete("delete from emp where id = #{id}")
public void delete(Integer id);
若mapper接口方法形参只有一个普通类型的参数,#{…}里面的属性名可以随便写,如#{id},#{value}。
日志输出
在application.properties中,打开mybatis的日志,并指定输出到控制台。
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutlmpl
不用记,写下提示词mybatis和log就有了
SQL注入
通过输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。
怎样算登录成功?
执行select count(*) from emp where username = ' ' and password = ' ' ;
,若输出不为0,则说明账户密码正确
可是,
但密码为如图所示时,则变为
select count(*) from emp where username = 'wu' and password = '' or '1'='1' ;
此时,语义发生了变化,1=1
永远为真.
参数占用符
一个问号代表一个参数。
此时,有两个参数,输入的两个参数会分别替换?
#{...}
执行SQL时,会将#{...}
替换为?
,生成预编译SQL,会自动设置参数值
使用时机:参数传递
${...}
拼接SQL,直接将参数拼接在SQL语句中,存在SQL注入问题
使用时机:对表名、列表进行动态设置时
新增
SQL语句:
insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)
values('songyuanqiao','宋远桥','1','1.jpg','2012-10-09','2022-10-01 10:00:00','2022-10-01 10:00:00');
接口方法:
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
"values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId}),#{createTime},#{updateTime})")
public void insert(Emp emp);
把多个参数传递用一个对象emp封装,只需传递一个参数就行了
注意:类对象的属性名都是驼峰命名法;数据库中的字段名是有下划线的
新增(主键返回)
描述:在数据库添加成功后,需要获取插入数据库数据的主键
如:添加套餐数据时,还需要维护套餐菜品关系表数据
实现:
@Options(keyProperty = "id",useGeneratedKeys=true)
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
"values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId}),#{createTime},#{updateTime})")
public void insert(Emp emp);
useGeneratedKeys=true表示要拿到主键名,keyProperty = "id"表示拿到的主键会封装到对象的id属性当中
@Data
public class Emp{
private Integer id;
private String username;
private String password;
private String name;
private Short gender;
private LocalDate entrydate;
private Integer deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
更新
SQL语句(根据ID更新员工信息)
update emp set username='songdaxia', name='宋大侠',gender='1',image='1.jpg',job=2,entrydate='2012-01-01',dept_id=2,update_time='2022-10-01 12:12:12'
where id =19;
接口方法:
@Update("update emp set username=#{
username}, name=#{
name},gender=#{
gender},image=#{
images},job=#{
job},entrydate=#{
entrydate},dept_id=#{
deptId},update_time=#{
updateTime}
where id =#{
Id}")
public void update(Emp,emp);
查询(根据ID查询)
SQL语句:
select * from emp where id = 19;
接口方法:
@Select("select * from emp where id =#{id}")
public Emp getById(Integer id);
数据封装
实体类属性名 和 数据库表查询返回的字段名一致,mybatis会自动封装
若实体类属性名 和 数据库表查询返回的字段名不一致,不能自动封装。
解决方案:开启mybatis的驼峰命名自动映射开关
步骤:在resources下的application,properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true
查询(条件查询)
SQL语句:
select * from emp
where name like '%张%' and gender = 1 and entrydate between '2010-01-01' and '2020-01-01'
order by update_time desc;
接口方法:
@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映射文件
XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
XML映射文件的namespace属性为Mapper接口全限定名一致
XML映射文件中sql语句的id与Mapper接口的方法名一致,并且保持返回类型一致。
可以在IDEA按照Mybatis的插件
对于简单的增删改查功能,使用注解;若要实现复杂的SQL功能建议用XML
动态SQL
随着用户的输入或外部条件的变化而变化的SQL语句
if ,where
<if>
用于判断条件是否成立。使用test属性进行条件判断,若条件为true,则拼接SQL
<where>
只会在子元素有内容的情况下才插入where子句,而且会自动去除子句开头的and或or
<set>
动态地在行首插入SET关键字,并会删掉额外的逗号(用在update语句中)
foreach
SQL语句:
delete from emp where id in (1,2,3);
接口方法:
public void deleteByIds(List<Integer> ids);
XML映射文件
<!--批量删除员工 (1,2,3)-->
<!--
collection: 遍历的集合名称
item: 遍历出来的元素
separator: 每一个遍历使用的分隔符
open: 遍历开始前拼接的SQL片段
close: 遍历结束后拼接的SQL片段
-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
sql片段
<sql>
定义可重用的SQL片段
<include>
通过属性refid,指定包含的sql片段
<sql id="commonSelect">
select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time
from emp
</sql>
<select id="list" resultType="com.itheima.pojo.Emp">
<include refid="commonSelect"/>
<where>
<if test="name != null">
name like concat('%', #{name}, '%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>