JDBC和MyBatis的使用

JDBC

1.JDBC概述

JDBC 就是使用Java语言操作关系型数据库的一套API

全称:( Java DataBase Connectivity ) Java 数据库连接

JDBC和MyBatis的使用_第1张图片
我们开发的同一套Java代码是无法操作不同的关系型数据库,因为每一个关系型数据库的底层实现细节都不一样。如果这样,问题就很大了,在公司中可以在开发阶段使用的是MySQL数据库,而上线时公司最终选用oracle数据库,我们就需要对代码进行大批量修改,这显然并不是我们想看到的。我们要做到的是同一套Java代码操作不同的关系型数据库,而此时sun公司就指定了一套标准接口(JDBC),JDBC中定义了所有操作关系型数据库的规则。众所周知接口是无法直接使用的,我们需要使用接口的实现类,而这套实现类(称之为:驱动)就由各自的数据库厂商给出。

  • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
  • 可随时替换底层数据库,访问数据库的Java代码基本不变

以后编写操作数据库的代码只需要面向JDBC(接口),操作哪儿个关系型数据库就需要导入该数据库的驱动包,如需要操作MySQL数据库,就需要再项目中导入MySQL数据库的驱动包。如下图就是MySQL驱动包

2.JDBC的代码步骤

  • 创建工程,导入驱动jar包

  • 注册驱动

    Class.forName("com.mysql.jdbc.Driver");
    
  • 获取连接

    Connection conn = DriverManager.getConnection(url, username, password);
    

    Java代码需要发送SQL给MySQL服务端,就需要先建立连接

  • 定义SQL语句

    String sql =  “update…” ;
    
  • 获取执行SQL对象

    执行SQL语句需要SQL执行对象,而这个执行对象就是Statement对象

    Statement stmt = conn.createStatement();
    
  • 执行SQL

    stmt.executeUpdate(sql);  
    
  • 处理返回结果

  • 释放资源

完整代码演示:

/**
 * JDBC快速入门
 */
public class JDBCDemo {

    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db1";
        String username = "root";
        String password = "1234";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "update account set money = 2000 where id = 1";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //5. 执行sql
        int count = stmt.executeUpdate(sql);//受影响的行数
        //6. 处理结果
        System.out.println(count);
        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

3.API详解

3.1 DriverManager

DriverManager(驱动管理类)作用:

  • 注册驱动

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CjBKcxwl-1671149320901)(assets/image-20210725171339346.png)]

    registerDriver方法是用于注册驱动的,但是我们之前做的入门案例并不是这样写的。而是如下实现

    Class.forName("com.mysql.jdbc.Driver");
    

    我们查询MySQL提供的Driver类,看它是如何实现的,源码如下:

    JDBC和MyBatis的使用_第2张图片

    在该类中的静态代码块中已经执行了 DriverManager 对象的 registerDriver() 方法进行驱动的注册了,那么我们只需要加载 Driver 类,该静态代码块就会执行。而 Class.forName("com.mysql.jdbc.Driver"); 就可以加载 Driver 类。

    提示:

    • MySQL 5之后的驱动包,可以省略注册驱动的步骤
    • 自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
  • 获取数据库连接

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0AtKxjmP-1671149320901)(assets/image-20210725171355278.png)]

    参数说明:

    • url : 连接路径

      语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…

      示例:jdbc:mysql://127.0.0.1:3306/db1

      细节:

      • 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对

      • 配置 useSSL=false 参数,禁用安全连接方式,解决警告提示

    • user :用户名

    • poassword :密码

3.2 Connection

Connection(数据库连接对象)作用:

  • 获取执行 SQL 的对象
  • 管理事务
3.2.1 获取执行对象
  • 普通执行SQL对象

    Statement createStatement()
    

    入门案例中就是通过该方法获取的执行对象。

  • 预编译SQL的执行SQL对象:防止SQL注入

    PreparedStatement  prepareStatement(sql)
    

    通过这种方式获取的 PreparedStatement SQL语句执行对象是我们一会重点要进行讲解的,它可以防止SQL注入。

  • 执行存储过程的对象

    CallableStatement prepareCall(sql)
    

    通过这种方式获取的 CallableStatement 执行对象是用来执行存储过程的,而存储过程在MySQL中不常用,所以这个我们将不进行讲解。

3.2.2 事务管理

先回顾一下MySQL事务管理的操作:

  • 开启事务 : BEGIN; 或者 START TRANSACTION;
  • 提交事务 : COMMIT;
  • 回滚事务 : ROLLBACK;

MySQL默认是自动提交事务

接下来学习JDBC事务管理的方法。

Connection几口中定义了3个对应的方法:

  • 开启事务

在这里插入图片描述

参与autoCommit 表示是否自动提交事务,true表示自动提交事务,false表示手动提交事务。而开启事务需要将该参数设为为false。

  • 提交事务

在这里插入图片描述

  • 回滚事务

在这里插入图片描述

具体代码实现如下:

/**
 * JDBC API 详解:Connection
 */
public class JDBCDemo3_Connection {

    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "1234";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql1 = "update account set money = 3000 where id = 1";
        String sql2 = "update account set money = 3000 where id = 2";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();

        try {
            // ============开启事务==========
            conn.setAutoCommit(false);
            //5. 执行sql
            int count1 = stmt.executeUpdate(sql1);//受影响的行数
            //6. 处理结果
            System.out.println(count1);
            int i = 3/0;
            //5. 执行sql
            int count2 = stmt.executeUpdate(sql2);//受影响的行数
            //6. 处理结果
            System.out.println(count2);

            // ============提交事务==========
            //程序运行到此处,说明没有出现任何问题,则需求提交事务
            conn.commit();
        } catch (Exception e) {
            // ============回滚事务==========
            //程序在出现异常时会执行到这个地方,此时就需要回滚事务
            conn.rollback();
            e.printStackTrace();
        }

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}
3.3 Statement
3.3.1 概述

Statement对象的作用就是用来执行SQL语句。而针对不同类型的SQL语句使用的方法也不一样。

  • 执行DDL、DML语句

在这里插入图片描述

  • 执行DQL语句

在这里插入图片描述

该方法涉及到了 ResultSet 对象,而这个对象我们还没有学习,一会再重点讲解。

3.3.2 代码实现

*** 执行DML语句:**

/**
  * 执行DML语句
  * @throws Exception
  */
@Test
public void testDML() throws  Exception {
    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");
    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    Connection conn = DriverManager.getConnection(url, username, password);
    //3. 定义sql
    String sql = "update account set money = 3000 where id = 1";
    //4. 获取执行sql的对象 Statement
    Statement stmt = conn.createStatement();
    //5. 执行sql
    int count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数
    //6. 处理结果
    //System.out.println(count);
    if(count > 0){
        System.out.println("修改成功~");
    }else{
        System.out.println("修改失败~");
    }
    //7. 释放资源
    stmt.close();
    conn.close();
}
3.4 ResultSet
3.4.1 概述

ResultSet(结果集对象)作用:

  • 封装了SQL查询语句的结果。

而执行了DQL语句后就会返回该对象,对应执行DQL语句的方法如下:

ResultSet  executeQuery(sql):执行DQL 语句,返回 ResultSet 对象

那么我们就需要从 ResultSet 对象中获取我们想要的数据。ResultSet 对象提供了操作查询结果数据的方法,如下:

boolean next()

  • 将光标从当前位置向前移动一行
  • 判断当前行是否为有效行

方法返回值说明:

  • true : 有效航,当前行有数据
  • false : 无效行,当前行没有数据

xxx getXxx(参数):获取数据

  • xxx : 数据类型;如: int getInt(参数) ;String getString(参数)
  • 参数
    • int类型的参数:列的编号,从1开始
    • String类型的参数: 列的名称

如下图为执行SQL语句后的结果

JDBC和MyBatis的使用_第3张图片

一开始光标指定于第一行前,如图所示红色箭头指向于表头行。当我们调用了 next() 方法后,光标就下移到第一行数据,并且方法返回true,此时就可以通过 getInt("id") 获取当前行id字段的值,也可以通过 getString("name") 获取当前行name字段的值。如果想获取下一行的数据,继续调用 next() 方法,以此类推。

3.4.2 代码实现
/**
  * 执行DQL
  * @throws Exception
  */
@Test
public void testResultSet() throws  Exception {
    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");
    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    Connection conn = DriverManager.getConnection(url, username, password);
    //3. 定义sql
    String sql = "select * from account";
    //4. 获取statement对象
    Statement stmt = conn.createStatement();
    //5. 执行sql
    ResultSet rs = stmt.executeQuery(sql);
    //6. 处理结果, 遍历rs中的所有数据
    /* // 6.1 光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()){
            //6.2 获取数据  getXxx()
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double money = rs.getDouble(3);

            System.out.println(id);
            System.out.println(name);
            System.out.println(money);

            System.out.println("--------------");

        }*/
    // 6.1 光标向下移动一行,并且判断当前行是否有数据
    while (rs.next()){
        //6.2 获取数据  getXxx()
        int id = rs.getInt("id");
        String name = rs.getString("name");
        double money = rs.getDouble("money");

        System.out.println(id);
        System.out.println(name);
        System.out.println(money);

        System.out.println("--------------");
    }

    //7. 释放资源
    rs.close();
    stmt.close();
    conn.close();
}

MyBatis

1.1 Mybatis概述

1.1.1 Mybatis概念
  • MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发

  • MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github

  • 官网:https://mybatis.org/mybatis-3/zh/index.html

持久层:

  • 负责将数据到保存到数据库的那一层代码。

    以后开发我们会将操作数据库的Java代码作为持久层。而Mybatis就是对jdbc代码进行了封装。

  • JavaEE三层架构:表现层、业务层、持久层

    三层架构在后期会给大家进行讲解,今天先简单的了解下即可。

框架:

  • 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
  • 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展
1.1.2 JDBC 缺点

下面是 JDBC 代码,我们通过该代码分析都存在什么缺点:

JDBC和MyBatis的使用_第4张图片

  • 硬编码

    • 注册驱动、获取连接

      上图标1的代码有很多字符串,而这些是连接数据库的四个基本信息,以后如果要将Mysql数据库换成其他的关系型数据库的话,这四个地方都需要修改,如果放在此处就意味着要修改我们的源代码。

    • SQL语句

      上图标2的代码。如果表结构发生变化,SQL语句就要进行更改。这也不方便后期的维护。

  • 操作繁琐

    • 手动设置参数

    • 手动封装结果集

      上图标4的代码是对查询到的数据进行封装,而这部分代码是没有什么技术含量,而且特别耗费时间的。

1.1.3 Mybatis 优化
  • 硬编码可以配置到配置文件
  • 操作繁琐的地方mybatis都自动完成

如图所示

JDBC和MyBatis的使用_第5张图片

下图是持久层框架的使用占比。
JDBC和MyBatis的使用_第6张图片

2 Mybatis的使用

1.1 环境准备

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

-- 删除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 实体类。

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 目录下创建包及测试用例。项目结构如下:

JDBC和MyBatis的使用_第7张图片

  • 安装 MyBatisX 插件

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

    • 主要功能

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

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

      JDBC和MyBatis的使用_第8张图片

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

    • 插件效果

      JDBC和MyBatis的使用_第9张图片

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

JDBC和MyBatis的使用_第10张图片

1.2 查询所有数据

JDBC和MyBatis的使用_第11张图片

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

  • 编写接口方法:Mapper接口

    • 参数:无

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

      在这里插入图片描述

    • 结果:List

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

    JDBC和MyBatis的使用_第12张图片

    • 执行方法、测试
    1.3代码演示:
#### 编写接口方法

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

public interface BrandMapper {

    /**
     * 查询所有
     */
    List<Brand> selectAll();
}

#### 编写SQL语句

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

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//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">
        select *
        from tb_brand;
    </select>
</mapper>

#### 编写测试方法

在 `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 brandMapper = sqlSession.getMapper(BrandMapper.class);

    //4. 执行方法
    List<Brand> brands = brandMapper.selectAll();
    System.out.println(brands);

    //5. 释放资源
    sqlSession.close();

}

执行测试方法结果如下:
JDBC和MyBatis的使用_第13张图片

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

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

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

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

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

<select id="selectAll" resultType="brand">
    select
    id, brand_name as brandName, company_name as companyName, ordered, description, status
    from 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.5 使用resultMap解决上述问题

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

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

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

    <resultMap id="brandResultMap" type="brand">
        
        <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.6 小结

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

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

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

 <resultMap id="brandResultMap" type="brand">
     
     <result column="brand_name" property="brandName"/>
     <result column="company_name" property="companyName"/>
resultMap>



<select id="selectAll" resultMap="brandResultMap">
    select *
    from tb_brand;
select>

3 查询详情

JDBC和MyBatis的使用_第15张图片

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

查看详情功能实现步骤:

  • 编写接口方法:Mapper接口

    • 参数:id

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

    • 结果:Brand

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

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

    JDBC和MyBatis的使用_第16张图片

  • 执行方法、进行测试

3.1 编写接口方法

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

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

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

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

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

3.3 编写测试方法

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

 @Test
public void testSelectById() throws IOException {
    //接收参数,该id以后需要传递过来
    int id = 1;

    //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 brandMapper = sqlSession.getMapper(BrandMapper.class);

    //4. 执行方法
    Brand brand = brandMapper.selectById(id);
    System.out.println(brand);

    //5. 释放资源
    sqlSession.close();
}

执行测试方法结果如下:

JDBC和MyBatis的使用_第17张图片

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>
    

    重新运行查看结果如下:

    JDBC和MyBatis的使用_第18张图片

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

3.5 parameterType使用

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

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

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

JDBC和MyBatis的使用_第19张图片

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

  • 转义字符

    下图的 < 就是 < 的转义字符。

    JDBC和MyBatis的使用_第20张图片

  • JDBC和MyBatis的使用_第21张图片

4其他查询:

代码演示:



<mapper namespace="com.laila.mapper.BrandMapper">

    <resultMap id="brandResultMap" type="brand">
        <result column="brand_name" property="brandName" />
        <result column="company_name" property="companyName" />
    resultMap>

    <select id="selectAll" resultMap="brandResultMap">
        select
         *
        from tb_brand;
    select>





    
    <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>


    <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>

    <update id="updateAll">
        update tb_brand
        set brand_name = #{brandName},company_name = #{companyName},ordered = #{ordered},description = #{description},status = #{status}
        where id = #{id};
    update>


    <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 and status != ''">
                    status = #{status}
                if>
            set>
        where id = #{id};
    update>

    <delete id="deleteById">
        delete
        from tb_brand
        where id = #{id};
    delete>
    

    <delete id="deleteByIds">
        delete
        from tb_brand where id
        in (
            <foreach collection="ids" item="id" separator=",">
                #{id}
            foreach>
                                );
    delete>
public interface BrandMapper {
    //查询所有
    List<Brand> selectAll();

    @ResultMap
    ("brandResultMap")@Select("select * from tb_brand where id =#{id};")
    //查看详情 id
    Brand selectById(int id);

    /*
    条件查询
    ☆参数接收
       1.散装参数:如果方法中有多个参数,需要使用@Param ( "SQL参数占位符名称")
       2.对象参数
       3. map集合参数
       多个参数或者数组啥的都会默认设为map集合 所以一定要用注解 这样的话 #{}括号里面的才能填参数的名称
     */

    //List selectByCondition(@Param("status") int status,@Param ("companyName") String companyName,@Param("brandName")String brandName);
    List<Brand> selectByCondition(Brand brand);
    //List selectByCondition(Map map);


    //增加数据
    void add(Brand brand);

    //修改全部信息
    void updateAll(Brand brand);

    //修改部分信息
    void update(Brand brand);

    //根据ID删除
    void deleteById(int id);

    //批量删除
    void deleteByIds(@Param("ids") int[] ids);


}

测试类:

public class MybatisTest {
    @Test
    public void testSelectAll() throws IOException {
        //1.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        List<Brand> brands = mapper.selectAll();

        System.out.println(brands);

        sqlSession.close();
    }
    @Test
    public void testSelectById() throws IOException {
        //
        int id = 1;

        //1.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        Brand brand = mapper.selectById(id);

        System.out.println(brand);


        sqlSession.close();
    }
    @Test
    public void testSelectByCondtion() 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.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        List<Brand> brands = mapper.selectByCondition(brand);

        System.out.println(brands);


        sqlSession.close();
    }

    @Test
    public void testadd() throws IOException {
        //接收参数


        int status = 1;
        String companyName = "苹果手机";
        String brandName = "手机";
        String description = "手机王中王";
        int ordered = 100;

        //处理参数
//        companyName ="%" + companyName + "%";
//        brandName ="%" + brandName + "%";

        //封装对象
        Brand brand = new Brand();

        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);
        brand.setDescription(description);
        brand.setOrdered(ordered);

        //1.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4.执行方法


//        //提交事务
//        sqlSession.commit();

        sqlSession.close();
    }
    @Test
    public void testUpdateAll() throws IOException {
        //接收参数
        int id =5;
        int status = 1;
        String companyName = "中华人民共和国国籍有限公司";
        String brandName = "RNG";
        String description = "我支持RNG,我有日本国籍";
        int ordered = 1000;

        //处理参数
//        companyName ="%" + companyName + "%";
//        brandName ="%" + brandName + "%";

        //封装对象
        Brand brand = new Brand();
        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);
        brand.setDescription(description);
        brand.setOrdered(ordered);
        brand.setId(id);

        //1.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4.执行方法
        mapper.update(brand);

//        //提交事务
//        sqlSession.commit();

        sqlSession.close();
    }
    @Test
    public void testUpdate() throws IOException {
        //接收参数
        int id =7;
        int status = 1;
        String companyName = "爱疯技术有限公司";
        String brandName = "iPhone";
//        String description = "";
//        int ordered = 1000;

        //处理参数
//        companyName ="%" + companyName + "%";
//        brandName ="%" + brandName + "%";

        //封装对象
        Brand brand = new Brand();
        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);
//        brand.setDescription(description);
//        brand.setOrdered(ordered);
        brand.setId(id);

        //1.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4.执行方法
        mapper.update(brand);

//        //提交事务
//        sqlSession.commit();

        sqlSession.close();
    }
    //删除
    @Test
    public void testDelete() throws IOException {
        //接收参数
        int id =6;
//        int status = 1;
//        String companyName = "爱疯技术有限公司";
//        String brandName = "iPhone";
//        String description = "";
//        int ordered = 1000;

        //处理参数
//        companyName ="%" + companyName + "%";
//        brandName ="%" + brandName + "%";

        //封装对象
//        Brand brand = new Brand();
//        brand.setStatus(status);
//        brand.setCompanyName(companyName);
//        brand.setBrandName(brandName);
//        brand.setDescription(description);
//        brand.setOrdered(ordered);
//        brand.setId(id);

        //1.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4.执行方法
        mapper.deleteById(id);

//        //提交事务
//        sqlSession.commit();

        sqlSession.close();
    }
    //批量删除
    @Test
    public void testDeleteByIds() throws IOException {
        //接收参数
        int[] ids = {5,7,8};
//        int status = 1;
//        String companyName = "爱疯技术有限公司";
//        String brandName = "iPhone";
//        String description = "";
//        int ordered = 1000;

        //处理参数
//        companyName ="%" + companyName + "%";
//        brandName ="%" + brandName + "%";

        //封装对象
//        Brand brand = new Brand();
//        brand.setStatus(status);
//        brand.setCompanyName(companyName);
//        brand.setBrandName(brandName);
//        brand.setDescription(description);
//        brand.setOrdered(ordered);
//        brand.setId(id);

        //1.加载mybatis的核心配置文件 获取SqlSessionFactory
        String resource = "mybatis-config.xml" ;
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3.
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4.执行方法
        mapper.deleteByIds(ids);

//        //提交事务
//        sqlSession.commit();

        sqlSession.close();
    }

你可能感兴趣的:(JavaWeb,mybatis,数据库,java)