【黑马】MyBatis

目录

  • MyBatis简介
      • JDBC缺点:
      • MyBatis针对于JDBC进行简化,简化思路:
  • MyBatis快速入门
    • 具体构建步骤
    • 解决SQL映射文件的警告提示
  • Mapper代理开发
    • 案例:使用Mapper代理方式完成案例
    • 具体步骤详解:
    • Mapper代理方式
  • Mapper核心配置文件
  • 配置文件完成增删改查
    • 1,配置文件实现CRUD
      • 1.1 环境准备
      • 1.2 查询所有数据
        • 1.2.1 编写接口方法
        • 1.2.2 编写SQL语句
        • 1.2.3 编写测试方法
        • 1.2.4 起别名解决上述问题
        • 1.2.5 使用resultMap解决上述问题
        • 1.2.6 小结
      • 1.3 查询详情
        • 1.3.1 编写接口方法
        • 1.3.2 编写SQL语句
        • 1.3.3 编写测试方法
        • 1.3.4 参数占位符
        • 1.3.5 parameterType使用
        • 1.3.6 SQL语句中特殊字段处理
      • 1.4 多条件查询
        • 1.4.1 编写接口方法
        • 1.4.2 编写SQL语句
        • 1.4.3 编写测试方法
        • 1.4.4 动态SQL
      • 1.5 单个条件(动态SQL)
        • 1.5.1 编写接口方法
        • 1.5.2 编写SQL语句
        • 1.5.3 编写测试方法
      • 1.6 添加数据
        • 1.6.1 编写接口方法
        • 1.6.2 编写SQL语句
        • 1.6.3 编写测试方法
        • 1.6.4 添加-主键返回
      • 1.7 修改
        • 1.7.1 编写接口方法
        • 1.7.2 编写SQL语句
        • 1.7.3 编写测试方法
      • 1.8 删除一行数据
        • 1.8.1 编写接口方法
        • 1.8.2 编写SQL语句
        • 1.8.3 编写测试方法
      • 1.9 批量删除
        • 1.9.1 编写接口方法
        • 1.9.2 编写SQL语句
        • 1.9.3 编写测试方法
      • 1.10 Mybatis参数传递
        • 1.10.1 多个参数
        • 1.10.2 单个参数
    • 2,注解实现CRUD

视频课程链接:黑马2小时MyBatis

配套源码下载

MyBatis简介

是一款持久层框架,用于简化JDBC开发

持久层就是

  • 负责将数据保存到数据库的那一层代码
  • JavaEE三层架构:表现层、业务层、持久层

表现层负责做页面展示的,业务层做逻辑处理,持久层对数据进行持久化

框架

框架就是

一个半成品软件,是一套可重用的、通用的、软件基础代码模型

在框架的基础上构建软件编写更加高效、规范、通用、可扩展

JDBC缺点:

1、硬编码

  • 注册驱动,获取连接
  • SQL语句

在这里插入图片描述

在这个位置写了很多字符串,这就叫硬编码。

如果字符串的值发生变动了,就要改动代码。这就意味着要重新编译,重新打包,重新运行,维护性差

2、操作繁琐

  • 手动设置参数
  • 手动封装结果集

在这里插入图片描述

MyBatis针对于JDBC进行简化,简化思路:

硬编码=》配置文件

操作繁琐=》让其自动完成

MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作

在这里插入图片描述

MyBatis快速入门

需求:

在这里插入图片描述

具体构建步骤

1、创建User表,添加数据,数据表准备如下:

//user.sql
create database mybatis;
use mybatis;drop table if exists tb_user;create table tb_user(id int primary key auto_increment,username varchar(20),password varchar(20),gender char(1),addr varchar(30)
);INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');

2、创建模块,导入坐标

使用Maven安装MyBatis,来构建项目,需将以下的依赖代码置于pom.xml文件中:

//pom.xml
<dependencies><!--mybatis 依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><!--mysql 驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency><!--junit 单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><!-- 添加slf4j日志api --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.20</version></dependency><!-- 添加logback-classic依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><!-- 添加logback-core依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version></dependency></dependencies>

logback除了这三个坐标信息之外,还需要一个配置文件,所以把logback.xml配置文件放在resources中

3、编写MyBatis核心配置文件,用来替换连接信息,解决硬编码的问题

在resources中创建一个新的文件mybatis-config.xml

在中进行配置

//mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><typeAliases><package name="com.itheima.pojo"/></typeAliases><!--environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!--数据库连接信息--><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/><property name="username" value="root"/><property name="password" value="1234"/></dataSource></environment><environment id="test"><transactionManager type="JDBC"/><dataSource type="POOLED"><!--数据库连接信息--><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/><property name="username" value="root"/><property name="password" value="1234"/></dataSource></environment></environments><mappers><!--加载sql映射文件--><!-- <mapper resource="com/itheima/mapper/UserMapper.xml"/>--><!--Mapper代理方式--><package name="com.itheima.mapper"/></mappers></configuration>

4、编写SQL映射文件,用来统一管理sql语句,解决硬编码问题

在中修改。

然后在resources中建立一个包mapper,用来存放Mapper文件:

如果写的是User表,那就是UserMapper.xml;如果写的是Order表,那就是OrdererMapper.xml

//UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间
--><mapper namespace="com.itheima.mapper.UserMapper"><!--statement--><select id="selectAll" resultType="pojo.User">select *from tb_user;</select></mapper>

namespace:名称空间

看这里面的标签,应该知道,之后的SQL语句应该就是写在这个Mapper中

resultType: 对应的返回结果的类型,id是唯一标识

在mybatis-config.xml文件中写加载sql映射文件

//mybatis-config.xml
<mapper resource="UserMapper.xml"/>

因为两个xml文件是平级的,所以直接写文件名字就行。

5、编码

1)定义POJO类

在java下创建一个包叫pojo,在包中创建一个User.java,里面内容如下:

package com.itheima.pojo;// alt + 鼠标左键 整列编辑
public class User {private Integer id;private String username;private String password;private String gender;private String addr;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getAddr() {return addr;}public void setAddr(String addr) {this.addr = addr;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", gender='" + gender + '\'' +", addr='" + addr + '\'' +'}';}
}

有了pojo类了,我们就可以在对应的UserMapper.xml的resultType中写返回类型是pojo.User。我们的需求是查询所有,所以id就起名为:selectAll。然后在标签里写SQL查询语句。

2)加载核心配置文件,获取SqlSessionFactory对象

在java下写一个核心测试类,MyBatisDemo.java

3)获取sqlSession对象,执行SQL语句

用sqlSession对象来执行SQL语句,具体如下:

//MyBatisDemo.java
package com.itheima;import com.itheima.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** Mybatis 快速入门代码*/
public class MyBatisDemo {public static void main(String[] args) throws IOException {//1. 加载mybatis的核心配置文件,获取 SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象,用它来执行sqlSqlSession sqlSession = sqlSessionFactory.openSession();//3. 执行sqlList<User> users = sqlSession.selectList("test.selectAll");System.out.println(users);//4. 释放资源sqlSession.close();}
}

Resources是java提供的一个资源加载类

selectOne() , selectList(),括号里放的是mapper的唯一标识

4)释放资源

解决SQL映射文件的警告提示

产生原因:IDEA和数据库没有建立连接,不识别表信息

解决方式:在IDEA中配置MySQL数据库连接

在这里插入图片描述

在这里插入图片描述

可以在IDEA中写SQL语句,有自动补全代码提示,很方便,打开IDEA数据库上面有个笔的标志。

Mapper代理开发

目的就是让MyBatis的代码更加简单。

解决原生方式中的硬编码问题;简化后期执行SQL

在这里插入图片描述

案例:使用Mapper代理方式完成案例

在这里插入图片描述

1、

▶️ 在java下创建一个mapper包,在这个下面写Mapper接口。

▶️ 要保证mapper接口和SQL映射文件(UserMapper.xml)在同一目录下,有两种做法:

1)把SQL映射文件直接放在mapper包。但是不建议用这种方式,因为映射文件属于是resources,放java下不方便管理。

2)在resources下建立一个mapper包,把UserMapper.xml放到这个里面(推荐使用!)

在resources下创建包的时候,发现没有package,只有directory,所以如果要创建多级包的话,需要用“/”进行分隔

2、Mapper接口全限定名:

//UserMapper.xml
<mapper namespace="com.itheima.mapper.UserMapper">

3、映射文件中的SQL语句的ID,保持与Mapper接口中定义方法一致

//UserMapper.java
List<User> selectAll();

记得要同时改配置文件的路径

//mybatis-config.xml
<mapper resource="com/itheima/mapper/UserMapper.xml"/>

4、编码main函数

package com.itheima;import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** Mybatis 代理开发*/
public class MyBatisDemo2 {public static void main(String[] args) throws IOException {//1. 加载mybatis的核心配置文件,获取 SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象,用它来执行sqlSqlSession sqlSession = sqlSessionFactory.openSession();//3. 执行sql//List<User> users = sqlSession.selectList("test.selectAll");//3.1 获取UserMapper接口的代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);List<User> users = userMapper.selectAll();System.out.println(users);//4. 释放资源sqlSession.close();}
}

具体步骤详解:

首先获取sqlSession,

 SqlSession sqlSession = sqlSessionFactory.openSession();

通过sqlSession来获取一个对应的mapper接口作为代理对象,通过

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

这行代码就能找到UserMapper这个接口,又因为在当前这个目录下,有一个同名的映射文件,所以可以找到对应的UserMapper.xml,接着找到里面对应的SQL语句。

然后通过UserMapper.selectAll();来调用他的方法。一调方法,这个方法对应的应该是一个sql语句的ID,然后通过这个ID找到这个文件里面对应的ID,有了ID就可以获取SQL语句。

又因为UserMapper.java中,selectAll的返回值是个List,所以它的底层执行的其实还是selectList,所以就相当于自动帮你写了selectList那行代码

Mapper代理方式

更简单的写法:

如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简
化SQL映射文件的加载

//mybatis-config.xml
<package name="com.itheima.mapper"/>

Mapper核心配置文件

mybatis-config.xml

  1. 用于配置数据库连接环境信息,可以配置多个用来配置多个数据库,比如开发的数据库,用于测试的数据库;还可以调整动态的切换数据源

    这个先不用修改,之后的Spring 会进行管理

    数据库连接池,MyBatis默认的是POOLED;不用修改,Spring管理

  2. 类型别名

    扫描com.itheima.pojo这个包下,给这个包里的所有实体类,起了一个别名,默认不区分大小写,也可以不用带包的名称,UserMapper.xml中的resultType里可以直接写那个别名

    <typeAliases><package name="com.itheima.pojo"/>
    </typeAliases>
    

注意:配置各个标签的时候,需要遵循前后顺序:

在这里插入图片描述

配置文件、注解两种方式

配置文件完成增删改查

就是将SQL语句写到配置文件里,完成条件查询,批量删除的操作

1,配置文件实现CRUD

在这里插入图片描述

如上图所示产品原型,里面包含了品牌数据的 查询按条件查询添加删除批量删除修改 等功能,而这些功能其实就是对数据库表中的数据进行CRUD操作。接下来我们就使用Mybatis完成品牌数据的增删改查操作。以下是我们要完成功能列表:

  • 查询
    • 查询所有数据
    • 查询详情
    • 条件查询
  • 添加
  • 修改
    • 修改全部字段
    • 修改动态字段
  • 删除
    • 删除一个
    • 批量删除

我们先将必要的环境准备一下。

1.1 环境准备

  • 数据库表(tb_brand)及数据准备

    -- tb_brand.sql
    -- 删除tb_brand表
    drop table if exists tb_brand;
    -- 创建tb_brand表
    create table tb_brand
    (-- id 主键id           int primary key auto_increment,-- 品牌名称brand_name   varchar(20),-- 企业名称company_name varchar(20),-- 排序字段ordered      int,-- 描述信息description  varchar(100),-- 状态:0:禁用  1:启用status       int
    );
    -- 添加数据
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),('小米', '小米科技有限公司', 50, 'are you ok', 1);
    
  • 实体类 Brand

    com.itheima.pojo 包下创建 Brand 实体类。

    //Brand.java
    public class Brand {// id 主键private Integer id;// 品牌名称private String brandName;// 企业名称private String companyName;// 排序字段private Integer ordered;// 描述信息private String description;// 状态:0:禁用  1:启用private Integer status;//省略 setter and getter。自己写时要补全这部分代码
    }
    
  • 编写测试用例

    测试代码需要在 test/java 目录下创建包及测试用例。项目结构如下:

    在这里插入图片描述

  • 安装 MyBatisX 插件

    • MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。

    • 主要功能

      • XML映射配置文件 和 接口方法 间相互跳转
      • 根据接口方法生成 statement
    • 安装方式

      点击 file ,选择 settings ,就能看到如下图所示界面

      在这里插入图片描述

      注意:安装完毕后需要重启IDEA

    • 插件效果

      在这里插入图片描述

      红色头绳的表示映射配置文件(UserMapper.xml),蓝色头绳的表示mapper接口(UserMapper.java)。在mapper接口点击红色头绳的小鸟图标会自动跳转到对应的映射配置文件,在映射配置文件中点击蓝色头绳的小鸟图标会自动跳转到对应的mapper接口。也可以在mapper接口中定义方法,自动生成映射配置文件中的 statement ,如图所示:

在这里插入图片描述

1.2 查询所有数据

在这里插入图片描述

如上图所示就页面上展示的数据,而这些数据需要从数据库进行查询。接下来我们就来讲查询所有数据功能,而实现该功能我们分以下步骤进行实现:

  • 编写接口方法:Mapper接口

    • 参数:无

      查询所有数据功能是不需要根据任何条件进行查询的,所以此方法不需要参数。

      在这里插入图片描述

    • 结果:List

      我们会将查询出来的每一条数据封装成一个 Brand 对象,而多条数据封装多个 Brand 对象,需要将这些对象封装到List集合中返回。

      在这里插入图片描述

    • 执行方法、测试

1.2.1 编写接口方法

java下的com.itheima.mapper 包写创建名为 BrandMapper.java 的接口。并在该接口中定义 List<Brand> selectAll() 方法。

public interface BrandMapper {/*** 查询所有*/List<Brand> selectAll();
}
1.2.2 编写SQL语句

reources 下创建 com/itheima/mapper 目录结构,并在该目录下创建名为 BrandMapper.xml 的映射配置文件,来编写SQL

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.itheima.mapper.BrandMapper"><select id="selectAll" resultType="brand">  //id和上面接口名一样select *from tb_brand;</select>
</mapper>
1.2.3 编写测试方法

testtest包中的 MybatisTest 类中编写测试查询所有的方法

@Test
public void testSelectAll() throws IOException {//1. 获取SqlSessionFactory对象,用这个对象去加载核心配置文件String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 然后来获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象,把BrandMapper.class传进去,返回一个brandMapper对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法,返回ListList<Brand> brands = brandMapper.selectAll();System.out.println(brands);//5. 释放资源sqlSession.close();}

注意:现在我们感觉测试这部分代码写起来特别麻烦,我们可以先忍忍。以后我们只会写上面的第3步的代码,其他的都不需要我们来完成。

执行测试方法结果如下:

在这里插入图片描述

从上面结果我们看到了问题,有些数据封装成功了,而有些数据并没有封装成功。为什么这样呢?

这个问题可以通过两种方式进行解决:

  • 给字段起别名
  • 使用resultMap定义字段和属性的映射关系
1.2.4 起别名解决上述问题

从上面结果可以看到 brandNamecompanyName 这两个属性的数据没有封装成功,查询 实体类 和 表中的字段 发现,在实体类中属性名是 brandNamecompanyName ,而表中的字段名为 brand_namecompany_name,如下图所示 。那么我们只需要保持这两部分的名称一致这个问题就迎刃而解。

在这里插入图片描述

我们可以在写sql语句时给这两个字段起别名,将别名定义成和属性名一致即可。

<select id="selectAll" resultType="brand">selectid, brand_name as brandName, company_name as companyName, ordered, description, statusfrom tb_brand;
</select>

而上面的SQL语句中的字段列表书写麻烦,如果表中还有更多的字段,同时其他的功能也需要查询这些字段时就显得我们的代码不够精炼。Mybatis提供了sql 片段可以提高sql的复用性。

SQL片段:

  • 将需要复用的SQL片段抽取到 sql 标签中

    <sql id="brand_column">id, brand_name as brandName, company_name as companyName, ordered, description, status
    </sql>
    

    id属性值是唯一标识,引用时也是通过该值进行引用。

  • 在原sql语句中进行引用

    使用 include 标签引用上述的 SQL 片段,而 refid 指定上述 SQL 片段的id值。

    <select id="selectAll" resultType="brand">select<include refid="brand_column" />from tb_brand;
    </select>
    
1.2.5 使用resultMap解决上述问题

起别名 + sql片段的方式可以解决上述问题,但是它也存在问题。如果还有功能只需要查询部分字段,而不是查询所有字段,那么我们就需要再定义一个 SQL 片段,这就显得不是那么灵活。

那么我们也可以使用resultMap来定义字段和属性的映射关系的方式解决上述问题。

  • 在映射配置文件中使用resultMap定义 字段 和 属性 的映射关系

    <resultMap id="brandResultMap" type="brand"><!--id:完成主键字段的映射column:表的列名property:实体类的属性名result:完成一般字段的映射column:表的列名property:实体类的属性名--><result column="brand_name" property="brandName"/><result column="company_name" property="companyName"/>
    </resultMap>
    

    注意:在上面只需要定义 字段名 和 属性名 不一样的映射,而一样的则不需要专门定义出来。

  • SQL语句正常编写

    <select id="selectAll" resultMap="brandResultMap">select *from tb_brand;
    </select>
    
1.2.6 小结

实体类属性名 和 数据库表列名 不一致,不能自动封装数据

  • ==起别名:==在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样
    • 可以定义 片段,提升复用性
  • ==resultMap:==定义 完成不一致的属性名和列名的映射

而我们最终选择使用 resultMap的方式。查询映射配置文件中查询所有的 statement 书写如下:

 <resultMap id="brandResultMap" type="brand"><!--id:完成主键字段的映射column:表的列名property:实体类的属性名result:完成一般字段的映射column:表的列名property:实体类的属性名--><result column="brand_name" property="brandName"/><result column="company_name" property="companyName"/>
</resultMap><select id="selectAll" resultMap="brandResultMap">select *from tb_brand;
</select>

1.3 查询详情

在这里插入图片描述

有些数据的属性比较多,在页面表格中无法全部实现,而只会显示部分,而其他属性数据的查询可以通过 查看详情 来进行查询,如上图所示。

查看详情功能实现步骤:

  • 编写接口方法:Mapper接口

  • 在这里插入图片描述

    • 参数:id

      查看详情就是查询某一行数据,所以需要根据id进行查询。而id以后是由页面传递过来。

    • 结果:Brand

      根据id查询出来的数据只要一条,而将一条数据封装成一个Brand对象即可

  • 编写SQL语句:SQL映射文件

    在这里插入图片描述

  • 执行方法、进行测试

1.3.1 编写接口方法

BrandMapper 接口中定义根据id查询数据的方法

/*** 查看详情:根据Id查询*/
Brand selectById(int id);
1.3.2 编写SQL语句

BrandMapper.xml 映射配置文件中编写 statement,使用 resultMap 而不是使用 resultType

<select id="selectById"  resultMap="brandResultMap">select *from tb_brand where id = #{id};
</select>

注意:上述SQL中的 #{id}先这样写,一会我们再详细讲解

1.3.3 编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法

 @Test
public void testSelectById() throws IOException {//接收参数,该id以后需要传递过来int id = 1;//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法Brand brand = brandMapper.selectById(id);System.out.println(brand);//5. 释放资源sqlSession.close();
}

执行测试方法结果如下:

在这里插入图片描述

1.3.4 参数占位符

查询到的结果很好理解就是id为1的这行数据。而这里我们需要看控制台显示的SQL语句,能看到使用?进行占位。说明我们在映射配置文件中的写的 #{id} 最终会被?进行占位。接下来我们就聊聊映射配置文件中的参数占位符。

mybatis提供了两种参数占位符:

  • #{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是 PreparedStatement,参数传递时候用,安全

  • ${} :拼接SQL。底层使用的是 Statement,会存在SQL注入问题,适合用在表名或者列名不固定的情况。如下图将 映射配置文件中的 #{} 替换成 ${} 来看效果

    <select id="selectById"  resultMap="brandResultMap">select *from tb_brand where id = ${id};
    </select>
    

    重新运行查看结果如下:

    在这里插入图片描述

==注意:==从上面两个例子可以看出,以后开发我们使用 #{} 参数占位符。

1.3.5 parameterType使用

对于有参数的mapper接口方法,我们在映射配置文件中应该配置 ParameterType 来指定参数类型。只不过该属性都可以省略。如下图:

<select id="selectById" parameterType="int" resultMap="brandResultMap">select *from tb_brand where id = ${id};
</select>
1.3.6 SQL语句中特殊字段处理

以后肯定会在SQL语句中写一下特殊字符,比如某一个字段大于某个值,如下图

在这里插入图片描述

可以看出报错了,因为映射配置文件是xml类型的问题,而 > < 等这些字符在xml中有特殊含义,所以此时我们需要将这些符号进行转义,可以使用以下两种方式进行转义

  • 转义字符

    下图的 &lt; 就是 < 的转义字符。

    在这里插入图片描述

  • <![CDATA[内容]]>

在这里插入图片描述

1.4 多条件查询

在这里插入图片描述

我们经常会遇到如上图所示的多条件查询,将多条件查询的结果展示在下方的数据列表中。而我们做这个功能需要分析最终的SQL语句应该是什么样,思考两个问题

  • 条件表达式
  • 如何连接

条件字段 企业名称品牌名称 需要进行模糊查询,所以条件应该是:

在这里插入图片描述

简单的分析后,我们来看功能实现的步骤:

  • 编写接口方法

    • 参数:所有查询条件
    • 结果:List
  • 在映射配置文件中编写SQL语句

  • 编写测试方法并执行

1.4.1 编写接口方法

BrandMapper 接口中定义多条件查询的方法。

而该功能有三个参数,我们就需要考虑定义接口时,参数应该如何定义。Mybatis针对多参数有多种实现:

  • 散装参数:

    如果方法中有多个参数,需要使用 @Param("参数名称") 标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位。

    List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName,@Param("brandName") String brandName);
    
  • **对象类封装参数:**对象的属性名称要和参数占位符名称一样

    将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和实体类属性名保持一致。

    List<Brand> selectByCondition(Brand brand);
    
  • map集合

    将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和map集合中键的名称一致。

    List<Brand> selectByCondition(Map map);
    
1.4.2 编写SQL语句

BrandMapper.xml 映射配置文件中编写 statement,使用 resultMap 而不是使用 resultType

<select id="selectByCondition" resultMap="brandResultMap">select *from tb_brandwhere status = #{status}and company_name like #{companyName}and brand_name like #{brandName}
</select>
1.4.3 编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法

@Test
public void testSelectByCondition() throws IOException {//接收参数int status = 1;String companyName = "华为";String brandName = "华为";// 处理参数companyName = "%" + companyName + "%";brandName = "%" + brandName + "%";//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法//方式一 :接口方法参数使用 @Param 方式调用的方法//List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);//方式二 :接口方法参数是 实体类对象 方式调用的方法//封装对象/* Brand brand = new Brand();brand.setStatus(status);brand.setCompanyName(companyName);brand.setBrandName(brandName);*///List<Brand> brands = brandMapper.selectByCondition(brand);//方式三 :接口方法参数是 map集合对象 方式调用的方法Map map = new HashMap();map.put("status" , status);map.put("companyName", companyName);map.put("brandName" , brandName);List<Brand> brands = brandMapper.selectByCondition(map);System.out.println(brands);//5. 释放资源sqlSession.close();
}
1.4.4 动态SQL

上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写,这个时候我们的SQL语句就不能那样写的

例如用户只输入 当前状态 时,SQL语句就是

select * from tb_brand where status = #{status}

而用户如果只输入企业名称时,SQL语句就是

select * from tb_brand where company_name like #{companName}

而用户如果输入了 当前状态企业名称 时,SQL语句又不一样

select * from tb_brand where status = #{status} and company_name like #{companName}

针对上述的需要,Mybatis对动态SQL有很强大的支撑:

  • if

  • choose (when, otherwise)

  • trim (where, set)

  • foreach

我们先学习 if 标签和 where 标签:

  • if 标签:条件判断

    • test 属性:逻辑表达式
    <select id="selectByCondition" resultMap="brandResultMap">select *from tb_brandwhere<if test="status != null">and status = #{status}</if><if test="companyName != null and companyName != '' ">and company_name like #{companyName}</if><if test="brandName != null and brandName != '' ">and brand_name like #{brandName}</if>
    </select>
    

    如上的这种SQL语句就会根据传递的参数值进行动态的拼接。如果此时status和companyName有值那么就会值拼接这两个条件。

    执行结果如下:

    在这里插入图片描述

    但是它也存在问题,如果此时给的参数值是

    Map map = new HashMap();
    // map.put("status" , status);
    map.put("companyName", companyName);
    map.put("brandName" , brandName);
    

    拼接的SQL语句就变成了

    select * from tb_brand where and company_name like ? and brand_name like ?
    

    而上面的语句中 where 关键后直接跟 and 关键字,这就是一条错误的SQL语句。这个就可以使用 where 标签解决。

    插一句,也可以改变语句来解决

    // 每一条前面都加and, 然后在最前面写where 1=1
    <select id="selectByCondition" resultMap="brandResultMap">select *from tb_brandwhere 1 = 1<if test="status != null">and status = #{status}</if><if test="companyName != null and companyName != '' ">and company_name like #{companyName}</if><if test="brandName != null and brandName != '' ">and brand_name like #{brandName}</if></select>
    
  • where 标签

    • 作用:
      • 替换where关键字
      • 会动态的去掉第一个条件前的 and
      • 如果所有的参数没有值则不加where关键字
    <select id="selectByCondition" resultMap="brandResultMap">select *from tb_brand<where><if test="status != null">and status = #{status}</if><if test="companyName != null and companyName != '' ">and company_name like #{companyName}</if><if test="brandName != null and brandName != '' ">and brand_name like #{brandName}</if></where>
    </select>
    

    注意:需要给每个条件前都加上 and 关键字

1.5 单个条件(动态SQL)

在这里插入图片描述

如上图所示,在查询时只能选择 品牌名称当前状态企业名称 这三个条件中的一个,但是用户到底选择哪儿一个,我们并不能确定。这种就属于单个条件的动态SQL语句。

这种需求需要使用到 choose(when,otherwise)标签 实现, 而 choose 标签类似于Java 中的switch语句,when就是case,otherwise就是default。

通过一个案例来使用这些标签

1.5.1 编写接口方法

BrandMapper 接口中定义单条件查询的方法。

/*** 单条件动态查询* @param brand* @return*/
List<Brand> selectByConditionSingle(Brand brand);
1.5.2 编写SQL语句

BrandMapper.xml 映射配置文件中编写 statement,使用 resultMap 而不是使用 resultType

<select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brand<where><choose><!--相当于switch--><when test="status != null"><!--相当于case-->status = #{status}</when><when test="companyName != null and companyName != '' "><!--相当于case-->company_name like #{companyName}</when><when test="brandName != null and brandName != ''"><!--相当于case-->brand_name like #{brandName}</when></choose></where>
</select>
1.5.3 编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法

@Test
public void testSelectByConditionSingle() throws IOException {//接收参数int status = 1;String companyName = "华为";String brandName = "华为";// 处理参数companyName = "%" + companyName + "%";brandName = "%" + brandName + "%";//封装对象Brand brand = new Brand();//brand.setStatus(status);brand.setCompanyName(companyName);//brand.setBrandName(brandName);//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法List<Brand> brands = brandMapper.selectByConditionSingle(brand);System.out.println(brands);//5. 释放资源sqlSession.close();
}

执行测试方法结果如下:

在这里插入图片描述

那么这里也有个问题,如果用户一个都不选,这个值就是空,where后面没有东西,就会报错,怎么解决呢,choose标签下还有一个标签,代码如下:

<select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brandwhere<choose><!--相当于switch--><when test="status != null"><!--相当于case-->status = #{status}</when><when test="companyName != null and companyName != '' "><!--相当于case-->company_name like #{companyName}</when><when test="brandName != null and brandName != ''"><!--相当于case-->brand_name like #{brandName}</when><otherwise>1=1</otherwise></choose>
</select>

但是推荐用标签,就不用特意写一个otherwise了

1.6 添加数据

在这里插入图片描述

如上图是我们平时在添加数据时展示的页面,而我们在该页面输入想要的数据后添加 提交 按钮,就会将这些数据添加到数据库中。接下来我们就来实现添加数据的操作。

  • 编写接口方法

    在这里插入图片描述

    参数:除了id之外的所有的数据。id对应的是表中主键值,而主键我们是 自动增长 生成的。不需要返回什么,所以void。

  • 编写SQL语句

    在这里插入图片描述

  • 编写测试方法并执行

明确了该功能实现的步骤后,接下来我们进行具体的操作。

1.6.1 编写接口方法

BrandMapper 接口中定义添加方法。

 /*** 添加*/
void add(Brand brand);
1.6.2 编写SQL语句

BrandMapper.xml 映射配置文件中编写添加数据的 statement

<insert id="add">insert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
1.6.3 编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法

@Test
public void testAdd() throws IOException {//接收参数int status = 1;String companyName = "波导手机";String brandName = "波导";String description = "手机中的战斗机";int ordered = 100;//封装对象Brand brand = new Brand();brand.setStatus(status);brand.setCompanyName(companyName);brand.setBrandName(brandName);brand.setDescription(description);brand.setOrdered(ordered);//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true); //设置自动提交事务,这种情况不需要手动提交事务了//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.add(brand);//4.1提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}

执行结果如下:

在这里插入图片描述

这里要注意!insert操作必须要有commit();操作(4.1),不然事务会回滚,记录进不了数据库。如果不写commit();,可以设置自动提交事务,这种情况不需要手动提交事务了

SqlSession sqlSession = sqlSessionFactory.openSession(true); 
1.6.4 添加-主键返回

在数据添加成功后,有时候需要获取插入数据库数据的主键(主键是自增长)。

比如:添加订单和订单项,如下图就是京东上的订单

在这里插入图片描述

订单数据存储在订单表中,订单项存储在订单项表中。

  • 添加订单数据

    在这里插入图片描述

  • 添加订单项数据,订单项中需要设置所属订单的id

    在这里插入图片描述

添加完订单项后,需要返回一个订单id,代表加在了这个订单中。

明白了什么时候 主键返回 。接下来我们简单模拟一下,在添加完数据后打印id属性值,能打印出来说明已经获取到了。

我们将上面添加品牌数据的案例中映射配置文件里 statement 进行修改,如下

<insert id="add" useGeneratedKeys="true" keyProperty="id">insert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>

在 insert 标签上添加如下属性:

  • useGeneratedKeys:是够获取自动增长的主键值。true表示获取。默认是false
  • keyProperty :指定将获取到的主键值封装到哪儿个属性里,也就是主键

1.7 修改

在这里插入图片描述

如图所示是修改页面,用户在该页面书写需要修改的数据,点击 提交 按钮,就会将数据库中对应的数据进行修改。注意一点,如果哪儿个输入框没有输入内容,我们是将表中数据对应字段值替换为空白还是保留字段之前的值?答案肯定是保留之前的数据。

接下来我们就具体来实现

1.7.1 编写接口方法

BrandMapper 接口中定义修改方法。

 /*** 修改*/
void update(Brand brand);

上述方法参数 Brand 就是封装了需要修改的数据,而id肯定是有数据的,这也是和添加方法的区别。

1.7.2 编写SQL语句

BrandMapper.xml 映射配置文件中编写修改数据的 statement

<update id="update">update tb_brand<set><if test="brandName != null and brandName != ''">brand_name = #{brandName},</if><if test="companyName != null and companyName != ''">company_name = #{companyName},</if><if test="ordered != null">ordered = #{ordered},</if><if test="description != null and description != ''">description = #{description},</if><if test="status != null">status = #{status}</if></set>where id = #{id};
</update>

set 标签可以用于动态包含需要更新的列,忽略其它不更新的列。

1.7.3 编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法

@Test
public void testUpdate() throws IOException {//接收参数int status = 0;String companyName = "波导手机";String brandName = "波导";String description = "波导手机,手机中的战斗机";int ordered = 200;int id = 6;//封装对象Brand brand = new Brand();brand.setStatus(status);//        brand.setCompanyName(companyName);//        brand.setBrandName(brandName);//        brand.setDescription(description);//        brand.setOrdered(ordered);brand.setId(id);//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法int count = brandMapper.update(brand);System.out.println(count);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}

在MyBatis中,当执行如updateinsertdelete这样的数据修改操作时,返回值通常表示的是这些操作影响的数据库记录的行数。

执行测试方法结果如下:

在这里插入图片描述

从结果中SQL语句可以看出,只修改了 status 字段值,因为我们给的数据中只给Brand实体对象的 status 属性设置值了。这就是 set 标签的作用。

1.8 删除一行数据

在这里插入图片描述

如上图所示,每行数据后面都有一个 删除 按钮,当用户点击了该按钮,就会将该行数据删除掉。那我们就需要思考,这种删除是根据什么进行删除呢?是通过主键id删除,因为id是表中数据的唯一标识。

接下来就来实现该功能。

1.8.1 编写接口方法

BrandMapper 接口中定义根据id删除方法。

/*** 根据id删除*/
void deleteById(int id);
1.8.2 编写SQL语句

BrandMapper.xml 映射配置文件中编写删除一行数据的 statement

<delete id="deleteById">delete from tb_brand where id = #{id};
</delete>
1.8.3 编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法

 @Test
public void testDeleteById() throws IOException {//接收参数int id = 6;//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.deleteById(id);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}

运行过程只要没报错,直接到数据库查询数据是否还存在。

1.9 批量删除

在这里插入图片描述

如上图所示,用户可以选择多条数据,然后点击上面的 删除 按钮,就会删除数据库中对应的多行数据。

1.9.1 编写接口方法

BrandMapper 接口中定义删除多行数据的方法。

/*** 批量删除*/
void deleteByIds(int[] ids);

参数是一个数组,数组中存储的是多条数据的id

1.9.2 编写SQL语句

BrandMapper.xml 映射配置文件中编写删除多条数据的 statement

编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用

foreach 标签

用来迭代任何可迭代的对象(如数组,集合)。

  • collection 属性:遍历哪个集合或数组
    • mybatis会将数组参数,封装为一个Map集合。
      • 默认:array = 数组
      • 使用@Param注解改变map集合的默认key的名称
  • item 属性:本次迭代获取到的元素。每一个元素
  • separator 属性:集合项迭代之间的分隔符。foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。
  • open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
  • close 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次
<delete id="deleteByIds">delete from tb_brand where idin<foreach collection="array" item="id" separator="," open="(" close=")">#{id}</foreach>;
</delete>

假如数组中的id数据是{1,2,3},那么拼接后的sql语句就是:

delete from tb_brand where id in (1,2,3);
1.9.3 编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法

@Test
public void testDeleteByIds() throws IOException {//接收参数int[] ids = {5,7,8};//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.deleteByIds(ids);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}

1.10 Mybatis参数传递

Mybatis 接口方法中可以接收各种各样的参数,如下:

  • 多个参数
  • 单个参数:单个参数又可以是如下类型
    • POJO 类型
    • Map 集合类型
    • Collection 集合类型
    • List 集合类型
    • Array 类型
    • 其他类型
1.10.1 多个参数

如下面的代码,就是接收两个参数,而接收多个参数需要使用 @Param 注解,那么为什么要加该注解呢?这个问题要弄明白就必须来研究Mybatis 底层对于这些参数是如何处理的。

User select(@Param("username") String username,@Param("password") String password);
<select id="select" resultType="user">select *from tb_userwhere username=#{username}and password=#{password}
</select>

我们在接口方法中定义多个参数,Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,而键在没有使用 @Param 注解时有以下命名规则:

  • 以 arg 开头 :第一个参数就叫 arg0,第二个参数就叫 arg1,以此类推。如:

    map.put(“arg0”,参数值1);

    map.put(“arg1”,参数值2);

  • 以 param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推。如:

    map.put(“param1”,参数值1);

    map.put(“param2”,参数值2);

代码验证:

  • UserMapper 接口中定义如下方法

    User select(String username,String password);
    
  • UserMapper.xml 映射配置文件中定义SQL

    <select id="select" resultType="user">select *from tb_userwhere username=#{arg0}and password=#{arg1}
    </select>
    

    或者

    <select id="select" resultType="user">select *from tb_userwhere username=#{param1}and password=#{param2}
    </select>
    
  • 运行代码结果如下

    在这里插入图片描述

    在映射配合文件的SQL语句中使用用 arg 开头的和 param 书写,代码的可读性会变的特别差,此时可以使用 @Param 注解。

在接口方法参数上使用 @Param 注解,Mybatis 会将 arg 开头的键名替换为对应注解的属性值。

代码验证:

  • UserMapper 接口中定义如下方法,在 username 参数前加上 @Param 注解

    User select(@Param("username") String username, String password);
    

    Mybatis 在封装 Map 集合时,键名就会变成如下:

    map.put(“username”,参数值1);

    map.put(“arg1”,参数值2);

    map.put(“param1”,参数值1);

    map.put(“param2”,参数值2);

  • UserMapper.xml 映射配置文件中定义SQL

    <select id="select" resultType="user">select *from tb_userwhere username=#{username}and password=#{param2}
    </select>
    
  • 运行程序结果没有报错。而如果将 #{} 中的 username 还是写成 arg0

    <select id="select" resultType="user">select *from tb_userwhere username=#{arg0}and password=#{param2}
    </select>
    
  • 运行程序则可以看到错误

    在这里插入图片描述

结论:以后接口参数是多个时,在每个参数上都使用 @Param 注解。这样代码的可读性更高。

1.10.2 单个参数
  • POJO 类型

    直接使用。要求 属性名参数占位符名称 一致

  • Map 集合类型

    直接使用。要求 map集合的键名参数占位符名称 一致

  • Collection 集合类型

    Mybatis 会将集合封装到 map 集合中,如下:

    map.put(“arg0”,collection集合);

    map.put(“collection”,collection集合;

    可以使用 @Param 注解替换map集合中默认的 arg 键名。

  • List 集合类型

    Mybatis 会将集合封装到 map 集合中,如下:

    map.put(“arg0”,list集合);

    map.put(“collection”,list集合);

    map.put(“list”,list集合);

    可以使用 @Param 注解替换map集合中默认的 arg 键名。

  • Array 类型

    Mybatis 会将集合封装到 map 集合中,如下:

    map.put(“arg0”,数组);

    map.put(“array”,数组);

    可以使用 @Param 注解替换map集合中默认的 arg 键名。

  • 其他类型

    比如int类型,参数占位符名称 叫什么都可以。尽量做到见名知意

建议:将来都是用@Param注解来修改Map集合中默认的键名,并使用修改后的名称来获取值,这样可读性更高!

2,注解实现CRUD

使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发

@Select(value = "select * from tb_user where id = #{id}")
public User select(int id);

注意:

  • 注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement

Mybatis 针对 CURD 操作都提供了对应的注解,已经做到见名知意。如下:

  • 查询 :@Select
  • 添加 :@Insert
  • 修改 :@Update
  • 删除 :@Delete

接下来我们做一个案例来使用 Mybatis 的注解开发

代码实现:

  • 将之前案例中 UserMapper.xml 中的 根据id查询数据 的 statement 注释掉

在这里插入图片描述

  • UserMapper 接口的 selectById 方法上添加注解

在这里插入图片描述

  • 运行测试程序也能正常查询到数据

我们课程上只演示这一个查询的注解开发,其他的同学们下来可以自己实现,都是比较简单。

==注意:==在官方文档中 入门 中有这样的一段话:

在这里插入图片描述

所以,注解完成简单功能,配置文件完成复杂功能。

而我们之前写的动态 SQL 就是复杂的功能,如果用注解使用的话,就需要使用到 Mybatis 提供的SQL构建器来完成,而对应的代码如下:

在这里插入图片描述

上述代码将java代码和SQL语句融到了一块,使得代码的可读性大幅度降低。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/397428.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ SQL ORM

测试代码 // // Created by www on 2024/8/7. // #include "sqlitepp/database.h" #include "sqlitepp/condition.h"#include <iostream> using namespace sqlitepp; using namespace sqlitepp::literals;enum class test_enum {hello };void test…

掌握这项技能,用Python爬虫定制你的私人电影推荐库

思路&#xff1a; 1、先选取你要获取的视频 2、用vip解析工具解析&#xff0c;获取地址 3、复制粘贴&#xff0c;获取视频 以下是效果图 需要的python模块&#xff1a; ##第一个模块不要安装&#xff0c;第二个模块需要安装 1、from multiprocessing import Pool 2、imp…

守护网站心脏:HAProxy负载均衡技术详解(全网最详细)

守护网站心脏&#xff1a;HAProxy负载均衡技术详解 文章目录 **守护网站心脏&#xff1a;HAProxy负载均衡技术详解**haproxy介绍特点功能配置结论 haproxy负载均衡测试haproxy主机操作日志重定向操作 webserver1主机操作webserver2主机操作 haporxy相关配置测试backup参数测速h…

【Redis】Redis 数据类型

文章目录 前言1 通用知识1.1 基本全局命令1.2 数据结构和内部编码 2 String2.1 类型介绍2.2 相关命令2.2.1 SET/GET 系列命令2.2.2 INCR/DECR 计数系列命令2.2.3 其他命令2.2.4 命令小结 2.3 内部编码2.4 应用场景2.4.1 缓存功能2.4.2 计数功能2.4.3 共享会话2.4.4 验证码功能 …

如何在linux上部署zabbix监控工具

<1>搭建服务机 1&#xff09;首先我们先执行 sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config ​ #然后我们再把防火墙开机自启关掉 马上生效 systemctl disable --now firewalld 2&#xff09;我们获得rpm包 rpm -Uvh https://mirrors.aliyun.com/…

Java设计模式-享元设计模式

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. 享元设计模式介绍1.1 定义1.2 原理1.3 使用场景1.4 注意事项 2. 享元设计模式角色2.1 抽象享元角色&#xff08;‌AbstractFlyWeight&#xff09;‌2.2 具体享元…

【MySQL】视图——视图、视图的概念、为什么要使用视图、视图的基本使用、视图规则和限制

文章目录 MySQL1. 视图1.1 视图的概念1.2 为什么要使用视图1.3 视图的基本使用1.4 视图规则和限制 MySQL 1. 视图 1.1 视图的概念 视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表…

【动态规划】1、不同路径II+2、三角形最小路径和

1、不同路径II&#xff08;难度中等&#xff09; 该题对应力扣网址 AC代码 只会写简单的if-else class Solution { public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {//1、定义子问题//2、子问题递推关系//3、确定dp数组的计算顺序…

uniapp获取swiper中子组件的内容高度

swiper有默认高度,如果不单独设置一个具体高度&#xff0c;swiper后面的内容将不会展示 这里展示的例子是: swiper中放有一个子组件,想要完整展示子组件的内容&#xff0c;swiper就需要获取到子组件的内容高度并设置 <!-- 注意: 这里的单位是 px,不是rpx --><swiper…

Element UI导航菜单刷新就复原问题解决方法~

1、首先要知道为什么一刷新就复原了&#xff0c;是因为default-active属性设置的是默认值&#xff0c;是一个死值&#xff0c;一旦刷新就会复原&#xff0c;造成高亮不能保持&#xff0c;那么怎么解决呢&#xff1f; 2、很简单&#xff0c;无需像一些博主一样绑定path。思路&a…

linux中信号的相关概念

信号 内核层和用户层通信的一种方式 信号类型 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18…

【限流与Sentinel超详细分析】

Sentinel 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件&#xff0c;主要以流量为切入点&#xff0c;从流量控制、熔断降级、系统自适应保护等多个维度来保障微服务的稳定性。 1 Sentinel 基本概念 资源…

MySQL —— 聚合查询,分组查询 与 联合查询

聚合函数 常见的统计总数、计算平局值等操作&#xff0c;可以使用聚合函数来实现&#xff0c;常见的聚合函数有&#xff1a; 函数说明count()统计数据总数sum()求和avg()求平均值max()求最大值min()求最小值 注意凡是涉及运算的&#xff0c;数据库会自动掉 NULL 值 注意NULL …

本地安Stable Diffusion全记录

这里写自定义目录标题 资料 资料 AI绘图软件Stable Diffusion 之本地安装 手把手教你在本机安装Stable Diffusion秋叶整合包 让 stable diffusion 局域网访问&#xff1a;详细解析配置步骤【Stable Diffusion 实战教程】 局域网多设备访问stable diffusion Stable Diffusion 老…

Lua语言基础学习:安装Lua和Lua库管理工具

Lua语言简介 Lua是一种轻量、高效、可嵌入的脚本语言&#xff0c;由巴西里约热内卢天主教大学的研究小组于1993年开发&#xff0c;Lua的解释器非常小巧&#xff0c;编译后的体积很小&#xff08;如完整解释器不过200KB&#xff09;&#xff0c;这使得它非常适合嵌入到其他应用程…

谷粒商城实战笔记-126-全文检索-ElasticSearch-整合-测试保存

文章目录 一&#xff0c;谷粒商城实战笔记-126-全文检索-ElasticSearch-整合-测试保存1&#xff0c;在Elasticsearch的配置类中增加通用设置2&#xff0c;索引数据3&#xff0c;验证 一&#xff0c;谷粒商城实战笔记-126-全文检索-ElasticSearch-整合-测试保存 1&#xff0c;在…

汇编语言基础及常见汇编指令

一、实验原理 x64dbg 是一款开源且免费的 Ring 3 级动态调试器&#xff0c;采用 QT 编写&#xff0c;支持 32 / 64 位程序。其反汇编引擎 BeaEngine 和 Capstone 功能极其强大&#xff0c;也有丰富的插件和脚本功能&#xff0c;且并保持更新&#xff0c;目前已经基本替代了 Ol…

数字医学影像系统PACS源码,三甲以下医院都能满足,C#语言开发,C/S架构系统成熟稳定,支持二次开发项目使用。

数字医学影像系统&#xff08;RIS/PACS&#xff09;源码&#xff0c;三甲以下的医院都能满足。开发技术&#xff1a;C/S架构&#xff0c;C#开发语言&#xff0c;数据库服务器采用Oracle数据库。 PACS系统模块组成 &#xff1a; 工作站&#xff1a; 分诊工作站、超声工作站、放…

学习鸿蒙-应用市场申请签名

1.需要的文件概念 .cer / .p7b / .p12 / .csr HarmonyOS应用/服务通过数字证书&#xff08;.cer文件&#xff09;和Profile文件&#xff08;.p7b文件&#xff09;来保证应用/服务的完整性。在申请数字证书和Profile文件前&#xff0c;首先需要通过DevEco Studio来生成密钥&am…

为具有公网IPV6地址的服务器安装nextcloudAIO并使用NginxProxyManager配置反向代理

软件和硬件环境 ubuntu server 24.04&#xff0c;并已配置好ipv6公网地址&#xff0c;已安装好docker和docker-compose。一块单独的硬盘&#xff0c;用于单独存储nextcloud数据。&#xff08;非必需&#xff09;有一个能够正常解析的域名&#xff0c;并已配置好AAAA记录解析。…