JavaWeb之MyBatis详解

MyBatis

  • 什么是MyBatis?
  1. MyBitis本是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBitis。2013年11月迁移到Github
  • 持久层
  1. 负责将数据保存到数据库的那一层代码
  2. javaEE三层架构:表现层,业务层,持久层
  • 框架
  1. 框架就是一个半成品软件,是一套可重用的,通用的,软件基础代码模型
  2. 在框架的基础之上构建软件编写更加高效,规范,通用,可扩展
  • JDBC缺点
  1. 硬编码
    • 注册驱动,获取连接
    • SQL语句
  2. 操作繁琐
    • 手动设置参数
    • 手动封装结果集

MyBatis快速入门

  • 查询user表中所有数据
  1. 创建user表,添加数据 **//**mysql中创建
create database mybatis;
use mybitis;
drop table if exists tb_user;
create table tb_user(
id int primary key auto_increment.
username varchar(20),
password varchar(20),
gender vhar(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', '男', '西安' );

建议:myBitis官网

  1. 创建模块,导入坐标

要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。

如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version> //选择版本3.5.7
</dependency>

pom.xml //内含很多依赖包,需要自行添加

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mybatis-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

<dependencies>  
    <!--mybatis依赖-->
    <dependency>
        <groupId> org.mybatis </groupId>
        <artifactId> mybatis </artifactId>
        <version> 3.5.7</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.5.6</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>
    <properties>
        <maven.compiler.source>13</maven.compiler.source>
        <maven.compiler.target>13</maven.compiler.target>
    </properties>

</project>
  1. 编写MyBitis核心配置文件—>替换连接信息 解决硬编码的问题

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>   
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <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?useSLL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--加载sql映射文件-->
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>
  1. 编写SQL映射文件—>统一管理sql语句,解决硬编码问题

UserMapper.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">


<!--
namespace:名称空间
-->
<mapper namespace="test">
    <select id="selectAll" resultType="com.itheima.pojo.User">//id就是查询的名字,resultType就是类的地址
        select * from tb_user;   //查询语句
    </select>
</mapper>

可以查看一下MyBatis得官网里面有详解

  1. 编码
    1. 定义POJO类
    2. 加载核心配置文件,获取SqlSessionFactory对象
    3. 获取SqlSession对象,执行SQL语句
    4. 释放资源

User类 获取数据库的数据

package com.itheima.pojo;

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", addr='" + addr + '\'' +
                '}';
    }
}

MyBatisDemo类 主类

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.加载mybitis的核心配置文件,获取sqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSessionFactory对象,用它来执行sql
        SqlSession sqlSession=sqlSessionFactory.openSession();
        //3.执行sql
        List<User> users = sqlSession.selectList("test.selectAll");
        //selectOne查找一个
        System.out.println(users);
        //4.释放资源
        sqlSession.close();
    }
}


解决SQL语句警告问题

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

image-20211208203021954

  • 产生原因:Idea和数据库没有建立连接,不识别表信息
  • 解决方法:在Idea中配置MYSQL数据库连接

image-20211207193743880

image-20211207195225052

image-20211207195253044


Mapper代理开发

  • 目的
  1. 解决了原生方法中的硬编码
  2. 简化后期执行SQL
   //3.执行sql
List<User> users=sqlSession.selectList("test.selectAll");
//3.获取接口代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//4.执行方法,其实就是执行sql语句
List<User> users = userMapper.selectAll();
  • 使用Mapper代理方式完成入门案例

image-20211208202947772

  1. 定义与SQL文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放在同一目录下

image-20211208174209205

image-20211208174256477

定义resource时,选择目录com/itheima/mapper(不能用.只能用/),将UserMapper.xml文件拖入其中。

  1. 设置SQL映射文件的namespace属性为Mapper接口全限定名(就是将名称空间改成接口文件位置)

image-20211208174711010

  1. 在Mapper接口中定义方法,方法名就是SQL映射文件中的sql语句中的id,并且保持参数类型和返回值类型一致

image-20211208175241079

  1. 编码
    1. 通过SqlSession的getMapper方法获取Mapper接口的代理对象
    2. 调用对应方法完成sql的执行

修改一下加载sql映射文件地址(之前把这个映射文件放入com.itheima.mapper文件下)

image-20211208180417795

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

image-20211208203233696


Mybatis核心配置文件

  • MyBatis核心配置文件的顶层结构

image-20211209144909410

  • environments,可以配置多个environment数据源,切换不同的数据库,比如开发的库和测试的库相互切换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8VaOMDW-1640340640383)(https://cdn.jsdelivr.net/gh/1wenjinjie/picture/img/202112091446550.png)]

  • 类型别名(typeAliases)
<typeAliases>
    <package name="com.itheima.pojo"/>
    </typeAliases>

image-20211209145305699

通过包扫描,取完别名后,resultType可以直接用类名//用别名可以简化配置

image-20211209145437123

细节:配置各个标签需要遵循顺序


配置文件完成增删改查

  • 准备环境
  1. 数据库tb_brand
use mybatis;
-- 删除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);


SELECT * FROM tb_brand;

image-20211210184132594

  1. 实体类Brand
package com.itheima.pojo;

/**
 * 品牌
 *
 * alt + 鼠标左键:整列编辑
 *
 * 在实体类中,基本数据类型建议使用其对应的包装类型
 */

public class Brand {
    // id 主键
    private Integer id;
    // 品牌名称
    private String brandName;
    // 企业名称
    private String companyName;
    // 排序字段
    private Integer ordered;
    // 描述信息
    private String description;
    // 状态:0:禁用  1:启用
    private Integer status;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public Integer getOrdered() {
        return ordered;
    }

    public void setOrdered(Integer ordered) {
        this.ordered = ordered;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brandName='" + brandName + '\'' +
                ", companyName='" + companyName + '\'' +
                ", ordered=" + ordered +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}

  1. 测试用例,写到test文件下,因为是Maven工程

image-20211210184431843

  1. 安装MyBatisX插件

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

主要功能:

  • XML和接口方法相互跳转
  • 根据接口方法生成statement

安装:

image-20211210184928809

  • 完成的功能列表清单:

    1. 查询
    • 查询所有数据

      image-20211211184218120

      1. 编写接口方法:Mapper接口

        参数:无

        结果:List

        List<Brand> selectAll();
        
      2. 编写SQL语句:SQL映射文件

        <select id="selectAll" resultType="brand">
            select * from tb_brand;
        </select>
        

        image-20211210190621393

      image-20211210191121659

      1. 执行方法测试

      MyBitisTest 类,测试类

      package com.itheima;
      
      import com.itheima.mapper.BrandMapper;
      import com.itheima.pojo.Brand;
      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 org.junit.Test;
      
      import java.io.InputStream;
      import java.util.List;
      
      public class MyBatisTest {
          @Test
          public void testSelectAll() throws Exception {
      
              //1.加载mybitis的核心配置文件,获取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();
          }
      }
      
      

      image-20211210192200479

    image-20211210192854670

    完成MyBatis完成操作需要几步?

    三步:编写接口方法->编写SQL->执行方法

    问题:上图中brandName以及companyName没有封装成功,因为mysql中字段为brand_Name,所以解决办法为:取别名

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4qpqRkmt-1640340640389)(C:\Users\wjj yes\AppData\Roaming\Typora\typora-user-images\image-20211210194807458.png)]

    因为每次查询都要写一次别名,用sql片段方便写字段名。

    image-20211210195715032

    • 除了取别名的方法,还可以用resultMap方法,也相当于取别名
    1. resultMap:
      • 定义标签
      • 在标签中,使用resultMap属性替换 resultType属性

    image-20211211182542694

    image-20211211182900442

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

    ​ 1.取别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样,可以定义片段,提升复用性

    ​ 2.resultMap:定义完成不一致的属性名和列名的映射.

    • 查看详情

    image-20211211184238623

    1. 编写接口方法:Mapper接口

    image-20211211190046279

    1. 参数:id
    2. 结果:Brand
    3. 编写SQL语句:SQL映射文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4RrmTxJb-1640340640392)(https://cdn.jsdelivr.net/gh/1wenjinjie/picture/img/202112111859959.png)]

    1. 执行方法,测试
    @Test
        public void testSelectById() throws Exception {
    
            int id =1;
    
            //1.加载mybitis的核心配置文件,获取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();
        }
    

    总结:

    * 参数占位符:
    1.#{}:会将其替换为 ? 为了防止SQL注入
    2.${}:拼sql。会存在SQL注入问题
    3.使用时机:
            参数传递的时候:#{}
            表名或者列名不固定的情况下:${}会存在sql注入
    4.特殊字符处理
            1.转义字符: 字符少用这个
            2.COATA区:字符多的话用这个(输入CD有提示)
    
    • 条件查询

    image-20211212210822635

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKLaiEnY-1640340640395)(C:\Users\wjj yes\AppData\Roaming\Typora\typora-user-images\image-20211212210839577.png)]

    第一种情况:查询散装参数

    • 编写方法接口:Mapper接口
      /**
         *  *参数接收
         *      1.散装参数:如果方法中有多个参数,需要使用@Param(" SQL参数占位符名称")
         *      2.对象参数
         *      3.map集合参数
         *
         */
        List<Brand> selectByCondition(@Param("status")int status, @Param("companyName")String companyName,@Param("brandName") String brandName);
    
    //    List<Brand> selectByCondition(Brand brand);
    //
    //    List<Brand> selectByCondition(Map map);
    

    image-20211212211340862

    • 参数:所有查询条件
        <select id="selectByCondition" resultMap="brandResultMap">
            select *
            from tb_brand
        where status=#{status}
                and company_name like #{companyName}
                and brand_name like #{brandName}
        </select>
    
    • image-20211212211435968

    • 结果:List

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

    • 执行方法,测试

     @Test
        public void testSelectByCondition() throws Exception {
            //接收参数
            int status = 1;
            String companyName = "华为";
            String brandName="华为";
    
            //参数处理
            companyName="%"+companyName+"%";
            brandName="%"+brandName+"%";
    
            //1.加载mybitis的核心配置文件,获取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.selectByCondition(status, companyName,brandName);
            System.out.println(brands);
            //5.释放资源
            sqlSession.close();
        }
    

    image-20211212212531107

    结果:

    image-20211212212613621

    第二种:对象参数(步骤和上面雷同)

    • 接口的定义
      List<Brand> selectByCondition(Brand brand);
    

    image-20211212213951704

    image-20211212214102311

    • 测试类(因为需要返回List对象,所以需要进行参数处理后封装对象
     @Test
        public void testSelectByCondition() throws Exception {
            //接收参数
            int status = 1;
            String companyName = "华为";
            String brandName="华为";
    
            //参数处理
            companyName="%"+companyName+"%";
            brandName="%"+brandName+"%";
    
            //封装对象
    
            Brand brand=new Brand();
            brand.setStatus(status);
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
    
            //1.加载mybitis的核心配置文件,获取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.selectByCondition(status, companyName,brandName);
            List<Brand> brands = brandMapper.selectByCondition(brand);
            System.out.println(brands);
            //5.释放资源
            sqlSession.close();
        }
    

    第三种:map集合参数

    • image-20211214213118548

    • image-20211214213139696

    • @Test
          public void testSelectByCondition() throws Exception {
              //接收参数
              int status = 1;
              String companyName = "华为";
              String brandName="华为";
      
              //参数处理
              companyName="%"+companyName+"%";
              brandName="%"+brandName+"%";
      
              //封装对象
      
      //        Brand brand=new Brand();
      //        brand.setStatus(status);
      //        brand.setBrandName(brandName);
      //        brand.setCompanyName(companyName);
      
              Map map = new HashMap();
              map.put("status",status);
              map.put("companyName",companyName);
              map.put("brandName",brandName);
      
              //1.加载mybitis的核心配置文件,获取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.selectByCondition(status, companyName,brandName);
              //List<Brand> brands = brandMapper.selectByCondition(brand);
              List<Brand> brands = brandMapper.selectByCondition(map);
              System.out.println(brands);
              //5.释放资源
              sqlSession.close();
          }
      

    **总结:**SQL语句设置多个参数有几种方式?

    1. 散装参数:需要使用@Param(“SQL中的参数占位符名称”)
    2. 实体类封装参数:只需要保证SQL中的参数名和实体类属性名对应上,即可设置成功
    3. map集合:只需要保证SQL中的参数名和map集合的键的名称对应上,即可设置成功
    • 查询-多条件-动态条件查询

    image-20211218170009312

    SQL语句会随着用户的输入或外部条件的变化而变化,我们称为动态SQL

    <select id="selectByCondition"resultMap="brandResultMap">
        select *
        from tb_brand
        where 
        	if(status!=null)
                status=#{status}
    	and company_name like #{companyName}
    	and brand_name like #{brandName}
    </select>
    
    • MyBatis对动态SQL有很强大的支撑
      1. if
      2. choose(when,otherwise)
      3. trim(where,set)
      4. foreach

    image-20211218161443004

    MyBatisTest.java

     @Test
        public void testSelectByCondition() throws Exception {
            //接收参数
            int status = 1;
            String companyName = "华为";
            String brandName="华为";
    
            //参数处理
            companyName="%" +companyName+ "%";
            brandName="%" +brandName+ "%";
    
            //封装对象
    
    //        Brand brand=new Brand() ;
    //        brand.setStatus(status);
    //        brand.setBrandName(brandName);
    //        brand.setCompanyName(companyName);
    
            Map map = new HashMap();
       //    map.put("status" ,status);
       //      map.put("companyName" ,companyName);
            map.put("brandName" ,brandName);
    
            //1.加载mybitis的核心配置文件,获取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.selectByCondition(status, companyName,brandName);
            //List<Brand> brands = brandMapper.selectByCondition(brand);
            List<Brand> brands = brandMapper.selectByCondition(map);
            System.out.println(brands);
            //5.释放资源
            sqlSession.close();
        }
    

    BrandMapper.xml

        <!--
            动态条件查询
                * if:条件判断
                    * test: 逻辑表达式
                 * 问题:
                    *恒等式
                    *<where>替换where 关键字
    
    -->
        <select id="selectByCondition" resultMap="brandResultMap">
            select *
            from tb_brand
          <where>
            <if test="status !=null">
                and   status =#{status}
            </if>
            <if test="companyName !=null  ">
                and  company_name like #{companyName}
            </if>
            <if test="brandName !=null    ">
                and brand_name like #{brandName}
            </if>
          </where>
        </select>
    

    其他文件和普通条件查询一样不变

    总结:

    if:用于判断参数是否有值,使用test属性进行条件判断

    1. 存在问题:第一个条件不需要逻辑运算符
    2. 解决方案

    使用恒等式让所有条件个数都一样

    标签替换where关键字

    • 单条件-动态条件查询

      image-20211218170034524

      从多个条件中选择一个

      choose(when,otherwise):选择,类似于Java中的switch语句

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GPvDRmwu-1640340640401)(https://cdn.jsdelivr.net/gh/1wenjinjie/picture/img/202112181701020.png)]

    BrandMapper.xml

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

    MyBatisTest.java

     @Test
        public void testSelectByConditionSingle() throws Exception {
            //接收参数
            int status = 1;
            String companyName = "华为";
            String brandName="华为";
    
            //参数处理
            companyName="%"+companyName+"%";
            brandName="%"+brandName+ "%";
    
            //封装对象
    
            Brand brand=new Brand() ;
            brand.setStatus(status);
          brand.setBrandName(brandName);
          brand.setCompanyName(companyName);
    
    //        Map map = new HashMap();
    //          map.put("status" ,status);
    //             map.put("companyName" ,companyName);
    //        map.put("brandName" ,brandName);
    
            //1.加载mybitis的核心配置文件,获取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.selectByCondition(status, companyName,brandName);
            //List<Brand> brands = brandMapper.selectByCondition(brand);
    //        List<Brand> brands = brandMapper.selectByCondition(map);
            List<Brand> brands = brandMapper.selectByConditionSingle(brand);
            System.out.println(brands);
            //5.释放资源
            sqlSession.close();
        }
    

    image-20211218170258529

    • 添加

    image-20211221235002173

    1. 编写接口方法:Mapper接口
    void add(Brand brand);
    

    image-20211221234107303

    • 参数:除了id之外的所有数据

    image-20211221234139498

    • 结果:void

    image-20211221234208700

    • 写SQL语句:SQL映射文件
        @Test
        public void testAdd() throws Exception {
            //接收参数
            int status = 1;
            String companyName = "波导手机";
            String brandName="波导";
            String description = "手机中的战斗机";
            int order =100;
    
    
    
    
            //封装对象
    
            Brand brand=new Brand() ;
            brand.setStatus(status);
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
            brand.setDescription(description);
            brand.setOrdered(order);
    
    //        Map map = new HashMap();
    //          map.put("status" ,status);
    //             map.put("companyName" ,companyName);
    //        map.put("brandName" ,brandName);
    
            //1.加载mybitis的核心配置文件,获取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.执行方法
            brandMapper.add(brand);
    
            //提交事务
            sqlSession.commit();
    
            //5.释放资源
            sqlSession.close();
        }
    

    若不行手动提交事务,可以选择自动提交

    image-20211221234716061

    将sqlSession改为true

    • 添加-主键返回

    image-20211221235438707

    在数据添加成功后,需要获取插入数据库数据的主键值

    比如:添加订单和订单项

    image-20211222000024787

    返回添加数据的主键 1.useGenerateKeys 2.KeyProperty

    <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>
    
    1. 修改
    • 修改全部字段

    image-20211222003339080

    image-20211222001945480

    image-20211222002011729

     @Test
        public void testUpdate() throws Exception {
            //接收参数
            int status = 1;
            String companyName = "波导手机";
            String brandName="波导";
            String description = "波导手机,手机中的战斗机";
            int order =200;
            int id= 5;
    
    
    
            //封装对象
    
            Brand brand=new Brand() ;
            brand.setStatus(status);
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
            brand.setDescription(description);
            brand.setOrdered(order);
            brand.setId(id);
    
    //        Map map = new HashMap();
    //          map.put("status" ,status);
    //             map.put("companyName" ,companyName);
    //        map.put("brandName" ,brandName);
    
            //1.加载mybitis的核心配置文件,获取sqlSessionFactory
            String 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();
    
            //3.获取Mapper接口的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            //4.执行方法
            int update = brandMapper.update(brand);
            System.out.println(update);
            //提交事务
              sqlSession.commit();
    
            //5.释放资源
            sqlSession.close();
        }
    
    • 修改动态字段

    image-20211222003319546

    动态修改就是只修改一些值,不修改全部值。具体和全部修改方法类似,只是sql语句变化

       <update id="update">
            update tb_brand
           <set>
                <if test="brandName !=null and brand_name !=' ' ">
                    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>
    
    1. 删除
    • 删除一个

    image-20211222195323678

    image-20211222195404193

    image-20211222195509499

    @Test
        public void deleteById() throws Exception {
            //接收参数
    
            int id= 4;
    
    
    
            //1.加载mybitis的核心配置文件,获取sqlSessionFactory
            String 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();
    
            //3.获取Mapper接口的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            //4.执行方法
    
            brandMapper.deleteById(id);
            //提交事务
            sqlSession.commit();
    
            //5.释放资源
            sqlSession.close();
        }
    

    结果:第4条数据没了

    image-20211222195549951

    • 批量删除

image-20211222201355940

  1. 编写接口方法

image-20211222201451992

  1. 编写SQL映射文件

image-20211222201527313

注意:mybatis会将数组参数封装为一个map集合,使用@Param注解改变map集合的默认key的名称

 @Test
    public void deleteByIds() throws Exception {
        //接收参数

       int [] ids={1,2,3};



        //1.加载mybitis的核心配置文件,获取sqlSessionFactory
        String 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();

        //3.获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4.执行方法

        brandMapper.deleteByIds(ids);
        //提交事务
        sqlSession.commit();

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

结果:1,2,3数据被删除

image-20211222201746646


参数传递

MyBatis接口方法1中可以接收各种各样的参数,MyBatis底层对于这些参数进行不同的封装处理方式

  • 单个参数:
  1. POJO类型:
  2. Map集合:
  3. Collection:
  4. List:
  5. Array:
  6. 其他类型
  • 多个参数:

用这个例子说明底层分装是Map集合

查询User表中username为zhangsan,password为123的信息

  1. 在UserMapper.java文件中添加
User select(@Param("username") String username, @Param("password") String password);
  1. 写sql语句
 <select id="select" resultType="user">
    select *
        from  tb_user
    where
            username =#{username}
        and password =#{password}


    </select>
  1. 创建一个执行类,大部分代码是类似的,不需要修改
  @Test
    public void testSelect() throws Exception {
        //接收参数



        //1.加载mybitis的核心配置文件,获取sqlSessionFactory
        String 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();

        //3.获取Mapper接口的代理对象
        UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);

        //4.执行方法

      String username="zhangsan";  //写的
      String password="123";		//写的
        User user = userMapper.select(username,password);  //写的
        System.out.println(user);		//写的
        //提交事务
        sqlSession.commit();

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

image-20211223193441870

通过debug方式查看mybatis底层如何封装数据,如果没用@Param,那么Map集合封装键值对是如下,如果使用@Param注解可以将主键修改成数据名字,替换成Map集合默认arg的键名,方便查看。

     * 多个参数:封装为Map集合
     * map.put("arg0",参数值1)
     * map.put("param1",参数值1)
     * map.put("arg1",参数值2)
     * map.put("param2",参数值2)
      *
 /*
     用@Param注解,替换Map集合中默认的arg键名
     * 单个参数:

     1. POJO类型:直接使用,属性名和参数占位符名称一致
     2. Map集合:直接使用,键名和参数占位符名称一致
     3. Collection:封装为Map集合
     * map.put("arg0",collection集合)
     * map.put("collection",collection集合)
     *
     4. List:封装为Map集合
     *  map.put("arg0",list集合)
     * map.put("collection",list集合)
     * map.put("list",list集合)
     *
     5. Array:
     *   map.put("arg0",Array数组)
     * map.put("array",Array数组)
     *
     6. 其他类型:直接使用

     * 多个参数:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
     * map.put("arg0",参数值1)
     * map.put("param1",参数值1)
     * map.put("arg1",参数值2)
     * map.put("param2",参数值2)
      */

image-20211223201523205

结论:无论如何 用@Param注解,替换Map集合中默认的arg键名


注解开发

区别:配置文件完成增删改查就是将sql语句写入配置文件,而注解开发技术将sql语句写到注解中。

image-20211223201537995

演示select的注解开发

image-20211223202626341

@Select("select * from tb_user where id = #{id}")

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值