赞
踩
Mybatis是一款优秀的持久层(Dao层/数据访问层)框架,用于简化JDBC的开发
Java DataBase Connectivity,就是使用Java语言操作关系型数据库的一套API
这个只是一套接口,而具体的实现则由各个厂商自己去实现,这也就是我们引入的驱动jar包,真正执行的代码是驱动jar包中的实现类
特点:复杂,硬编程
只需要关注application.properties 和 mapper接口
是一个容器,负责分配、管理数据库连接(Connection),允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。并且会释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏(类似线程池)
标准接口:DataSource
,由第三方实现该接口(默认使用Hikari)
切换连接池:在pom.xml中加入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
获取连接:Connection getConnection() throws SQLException;
是一个实用的Java类库,能通过注解的形式自动生成构造器,getter/setter、equals、hashcode、toString等方法,并可以自动生成日志变量,简化Java开发、提高效率。
使用方法:在pom.xml中加入
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
@Mapper 在mapper的接口上加上此注解表示运行时会自动创建该接口的代理对象,并且放入IOC容器中,
通过在Mapper接口中的对应接口方法上加上对应的注解,通过注解指定执行的操作和sql语句。
使用注解@Delete
@Delete("delete from emp where id = #{id}")
public void delete(Integer id);
如果mapper接口方法形参中只有一个普通类型的参数,#{}里面的属性名可以随便写,但是原则上更希望保持一致
可以在application.properties中,打开mybatis的日志,并指定输出到控制台。
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
这种使用预编译方式的占位符的访问方式可以防止SQL注入
SQL注入是指通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方式
比如我们在登录时,要输入用户名和密码,如果我们使用非预编译的方法,此时我们的密码会直接输入到sql语句中的password=' '
中,而如果我们的密码处输入'or'1'='1
,此时拼接进sql语句后,where password='' or '1' = '1'
,由于’1’一定等于’1’,因此这就为一个恒true的判断,不管password是否有等于''
的项,就代表where后的条件永远为true,因此我们在select count(*) from 用户表
的时候就永远count>0,从而登录成功。
使用预编译,此时不管你输入了什么,都会将输入的整个字符串当作参数传入,并且在传入前就对其余固定过的SQL语句部分进行了编译,而不是进行简单拼接成为SQL语句的一部分
而我们在使用Mybatis时用的#{}这个占位符就是预编译的sql语句,这个占位符最终会被?
代替
#{}
${}
如果新增表项有多个参数,可以使用实体类先去封装参数,之后用占位符去赋值,字段名和属性名要一一对应
使用注解@Insert
@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实体类属性
private Integer id;
private String username;
private String password;
private String name;
private Short gender;
private String image;
private Short job;
private LocalDate entrydate;
private Integer deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
通过参数传递后进行占位符赋值。
在数据添加成功后,需要获取插入数据库数据的主键。eg:添加套餐数据时,还需要维护套餐菜品关系表数据。即修改一个表后,可能还要对关联表修改信息,而此时就需要当前表的主键,这样才可以定位到关联表的对应表项。
实现方法:在mapper接口方法上加上注解
@Options(useGeneratedKeys = true,keyProperty = "id")
,true表示要获取主键值,"id"表示最后封装到实体类对象的id属性中
@Options(useGeneratedKeys = true,keyProperty = "id")
@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);
使用注解@Update
,需要用到主键
@Update("update emp set username = #{username},name = #{name}, gender= #{gender},image= #{image}," +
"job= #{job},entrydate= #{entrydate},dept_id= #{deptId},update_time= #{updateTime} where id = #{id}")
public void update(Emp emp);
返回单个记录,因此用一个单个的实体类就可以存储
使用注解@Select
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);
自动封装规则:实体类属性名和数据库查询返回的字段名一致,mybatis会自动封装;如果实体类属性名和数据库查询返回的字段名不一致,不能自动封装
解决方案
@Results({
@Result(column = "dept_id", property = "deptId"),
@Result(column = "create_time", property = "createTime")
})
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);
mybatis.configuration.map-underscore-to-camel-case=true
查询结果可能为多条记录,所以我们需要封装到一个List集合内
在进行模糊匹配时,如果使用#{},则在预编译时会变为?,但是在模糊匹配时,匹配字符串会用‘’包裹,如果变为?则为,‘%?%’这样就变为带?的模糊查询,所以我们在此时使用${}
,即?不可以出现在引号内
@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);
要解决这种可能引起sql注入的风险,就需要使用到sql语法里的concat函数
concat(‘hello’, ‘mysql’)=hellomysql
@Select("select * from emp where name like concat('%',#{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文件规范
resources内XML的包名要和java内的mapper接口包名一致,这样就是属于同一个包内。
全限定名指全类名
EmpMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--resultType为单条记录所封装的类型,也要全类名-->
<select id="list" resultType="com.itheima.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>
EmpMapper.java
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
基于IDEA的快速开发Mybatis的插件,为效率而生。
可以快速定位到两个关联的xml内的sql语句和mapper接口函数
可以自动构建xml配置
在写出mapper接口时使用 Alt+Enter就会自动构建
随着用户的输入或外部条件的变化而变化的SQL语句,我们成为动态SQL
比如我们在进行条件查询的时候,可能只要用1、2、3个条件,此时我们的SQL查询语句就要进行变化才可以。
用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL
用于动态生成where关键字,并且会自动删除语句中多余的and逻辑判断
<select id="list" resultType="com.itheima.pojo.Emp"> select * from emp <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>
用于在update语句中包裹更新字段,提供set关键字,并且去除多余的,
。
eg:批量删除
sql语句:delete from emp where id in (1,2,3);
< foreach collection="遍历的集合" item="遍历出来的元素" separator="元素分隔符" open="遍历开始前拼接的SQL片段" close="遍历结束后拼接的SQL片段" >遍历出来的元素< /foreach >
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
public void testDeleteByIds(){
List<Integer> ids = Arrays.asList(16,18,19);
empMapper.deleteByIds(ids);
}
提高代码的复用性
将XML文件中,将重复的代码片段抽取出来放在标签< sql >内,并且给此标签一个id,之后在需要使用这个代码片段的地方加上< include >标签,并且带上属性refid=“此sql标签id”
< sql id = "xxx" > ..... < /sql >
< include refid = "xxx"/>
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。