八、MyBatis

一、MyBatis介绍

MyBatis 是持久层框架,它支持自定义 SQL、存储过程以及⾼级映射。MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置 和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
1.1 MyBatis功能
MyBatis 是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库工具
2.2 框架交互流程图
MyBatis 也是⼀个 ORM 框架, ORM(Object Relational Mapping),即对象关系映射。在面向 对象编程语言中,将关系型数据库中的数据与对象建立起映射关系,进而自动的完成数据与对象 的互相转换:
(1)将输⼊数据(即传⼊对象)+SQL 映射成原生SQL
(2)将结果集映射为返回对象,即输出对象 ORM 把数据库映射为对象:
  • 数据库表(table)—> 类(class) 
  • 记录(record,行数据)—> 对象(object) 
  • 字段(field) —> 对象的属性(attribute)
一般的 ORM 框架,会将数据库模型的每张表都映射为⼀个 Java 类。 也就是说使用MyBatis 可以像操作对象⼀样来操作数据库中的表,可以实现对象和数据库表之间的转换。

二、搭建MyBatis开发环

添加MyBatis框架时要同时添加对应数据库驱动,他们总是成对存在
项目所需基本依赖
创建完SSM项目,项目中添加了Mybatis + MySQL.之后,项目启动,一定会报错!!!这是正常现象,因为没有配置数据库连接信息
2.1 注解实现Mybatis操作

yml文件配置数据库连接信息

spring:
  datasource:
#    user是数据库的名称
    url: jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&useSSL=false
#    数据库用户名
    username: root
#    数据库密码
    password: "123456"
通过注解来进行数据库的操作
(1)@Select

//Mapper层
@Mapper
public interface UserMapper {
   //查询所有⽤⼾ 
    @Select("select * from userinfo")
   public List queryAllUser();
}

//service层
@Service
public class UserService {
    @Autowired
  private   UserMapper userMapper;

    //查询所有用户
    public List<UserInfo> queryAllUser(){
        return userMapper.queryAllUser();
    }
}

//controller层
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    //查询所有用户
    @RequestMapping("/queryAllUser")
    public List<UserInfo> queryAllUser(){
        return userService.queryAllUser();
    }
}

使⽤#{} 的方式获取⽅法中的参数
public interface UserInfoMapper {
    @Select("select * from userinfo where id= #{id} ")
    UserInfo queryById(Integer id);
}

数据库中的字段名与Java中对象名字不一致时,如何配置让数据库与属性匹配?
2.2 XML实现Mybatis(前提配置Maven)
2.2.1 配置数据库连接信息
1、配置数据库连接信息
spring:
  datasource:
#    user是数据库的名称
    url: jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&useSSL=false
#    数据库用户名
    username: root
#    数据库密码
    password: "123456"
    driver-class-name: com.mysql.cj.jdbc.Driver
2.2.2 配置 MyBatis 映射文件位置路径
这个配置使 MyBatis 能够扫描指定目录下的所有映射文件,并将它们加载到 MyBatis 的配置中,以便在运行时使用这些映射文件中的 SQL 语句和映射规则。此处映射到当前目录的mapper目录下的所有带有·Mapper.xml的文件
声明接口
@Mapper
public interface UserXmlMapper {
//声明查询所有用户信息的接口
   public List<UserInfo> queryXmlAllUser();
}
2.2.3 xml文件实现sql语句查询

三、解决数据库字段名与java对象属性名不一致问题

如果Java属性和mysql的字段一样, mybatis会进行自动赋值,如果不一样,则不赋值
(1)起别名
(2)结果映射
使⽤ id 属性给该 Results 定义别名,使⽤ @ResultMap 注解来复⽤其他定义的 ResultMap
(3)开启驼峰命名
驼峰命名规则:abc_xyz=>abcXyz
• 表中字段名:abc_xyz
• 类中属性名:abcXyz
三、mybatis进阶
3.1 #{属性名}和${属性名}区别
当是$时,sql语句id中会被直接替换为设置的值
当是#时,sql语句中为预编译处理会被替换为?占位符
因此当 $: 如果是整数时,不受影响,当为字符串时直接为username=张三,但是sql只能识别username='张三',所以推荐使用#更安全
但在特定情况下只能使用$
比如给查询的数据排序select * from userinfo order by desc
此时传入排序规则desc/asc(逆序/顺序)必须使用 $直接替换,否则使用#会预编译处理识别成字符串加引号,这样sql识别,语句就会发生错误
#和$区别
1.$存在SQL注入的问题,会将参数作为sql的一部分,造成信息泄露等问题
2.$直接替换;#是预处理。
3. $使用注意事项:一定是可以穷举的值,在使用之前一定要对传递的值进行合法性验证(安全性验证)。

四、动态SQL

4.1 if标签
//Controller
//1、if标签
@RequestMapping("/addUserByIf")
public Integer addUserByIf(){
    UserInfo userInfo = new UserInfo();
    userInfo.setAge(11);
    userInfo.setPassword("ifififififfi");
    userInfo.setUsername("if标签测试2");
   return userXmlService.addUserByIf(userInfo);
}

//Service
//1、if标签
public Integer addUserByIf(UserInfo userInfo) {
  return userXmlMapper.addUserByIf(userInfo);
}

//Mapper
Integer addUserByIf(UserInfo userInfo);



//xm文件
//
<insert id="addUserByIf" >
    insert into userinfo(
            username,
         <if test="age != null">age,</if>
         <if test="gender != null">gender,</if>
                         password)
    values(
           #{username},
        <if test="age != null">#{age},</if>
        <if test="gender != null"> gender,</if>
          #{password}
          )
</insert>
注册信息时有必填字段和非必填字段,可以使用if标签实现sql。使用if标签中的内容,如果程序中有数据则将字段执行到sql中,否则sql排除该字段

4.2 trim标签
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表 整个语句块,以suffix的值作为后缀
prefixOverrides:表 整个语句块要去除掉的前缀
suffixOverrides:表 整个语句块要去除掉的后缀
<insert id="insertUserByCondition"> 
    INSERT INTO userinfo 
    <trim prefix="(" suffix=")" suffixOverrides=","> 
        <if test="username !=null"> username, </if> 
        <if test="password !=null"> password, </if> 
        <if test="age != null"> age, </if>
         <if test="gender != null"> gender, </if> 
        <if test="phone != null"> phone, </if> 
    </trim> 
    VALUES 
    <trim prefix="(" suffix=")" suffixOverrides=","> 
        <if test="username !=null"> #{username}, </if>
         <if test="password !=null"> #{password}, </if>
         <if test="age != null"> #{age}, </if> 
        <if test="gender != null"> #{gender}, </if> 
        <if test="phone != null">#{phone} </if> 
        </trim> 
</insert>
在以上sql动态解析时,会将第⼀个部分做如下处理:
基于 prefix 配置,开始部分加上 (
基于 suffix 配置,结束部分加上 )
多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于
suffixOverrides 配置去掉最后⼀个 ,
注意 中的 username 是传⼊对象的属性

4.3 where标签
<select id="queryByCondition" resultType="com.example.demo.model.UserInfo"> 
    select id, username, age, gender, phone, delete_flag, create_time, update_time from userinfo 
    <where> 
        <if test="age != null"> and age = #{age} </if> 
        <if test="gender != null"> and gender = #{gender} </if>
        <if test="deleteFlag != null"> and delete_flag = #{deleteFlag} </if>
     </where> 
</select>
删除代码块最前面的and
查询条件为空时去除where关键字

4.4 set标签
<update id="updateUserByCondition"> update userinfo 
    <set> 
        <if test="username != null"> username = #{username}, </if>
        <if test="age != null"> age = #{age}, </if> 
        <if test="deleteFlag != null"> delete_flag = #{deleteFlag}, </if> 
    </set> 
      where id = #{id} 
</update>
动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(⽤于update语句中)

4.5 foreach标签
对集合进⾏遍历时可以使⽤该标签。标签有如下属性:
collection:绑定方法参数中的集合,如List,Set,Map或数组对象
item:遍历时的每⼀个对象
open:语句块开头的字符串
close:语句块结束的字符串
separator:每次遍历之间间隔的字符串
<delete id="deleteByIds"> 
    delete from userinfo 
    where id in 
    <foreach collection="ids" item="id" separator="," open="(" close=")"> 
        #{id} 
    </foreach> 
</delete>

4.6 sql标签与include标签
<sql id="allColumn"> 
    id, username, age, gender, phone, delete_flag, create_time, update_time 
</sql>

<select id="queryAllUser" resultMap="BaseMap"> 
    select 
    <include refid="allColumn"></include> 
    from userinfo 
</select>

我们可以对重复的代码⽚段进⾏抽取,将其通过 标签封装到⼀个SQL⽚段,然后再通过标签进行引用。

定义可重用的SQL片段
通过属性refid,指定包含的SQL片段
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值