MyBatis 详细教程

2022-03-08 10:25:29 浏览数 (1)

MyBatis

目录树

  • tb_user.sql ```sql create database mybatis; use mybatis;
代码语言:txt复制
drop table if exists tb_user;
代码语言:txt复制
create table tb_user(
代码语言:txt复制
	id int primary key auto_increment,
代码语言:txt复制
	username varchar(20),
代码语言:txt复制
	password varchar(20),
代码语言:txt复制
	gender char(1),
代码语言:txt复制
	addr varchar(30)
代码语言:txt复制
);
代码语言:txt复制
INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
代码语言:txt复制
INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
代码语言:txt复制
INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');
代码语言:txt复制
INSERT INTO tb_user VALUES (4, '赵六', '111', '女', '上海');
代码语言:txt复制
```
  • pom.xml ```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>
代码语言:txt复制
    <groupId>com.ruochen</groupId>
代码语言:txt复制
    <artifactId>mybatis-demo</artifactId>
代码语言:txt复制
    <version>1.0-SNAPSHOT</version>
代码语言:txt复制
    <properties>
代码语言:txt复制
        <maven.compiler.source>8</maven.compiler.source>
代码语言:txt复制
        <maven.compiler.target>8</maven.compiler.target>
代码语言:txt复制
    </properties>
代码语言:txt复制
    <dependencies>
代码语言:txt复制
        <!--mybatis 依赖-->
代码语言:txt复制
        <dependency>
代码语言:txt复制
            <groupId>org.mybatis</groupId>
代码语言:txt复制
            <artifactId>mybatis</artifactId>
代码语言:txt复制
            <version>3.5.5</version>
代码语言:txt复制
        </dependency>
代码语言:txt复制
        <!--mysql 驱动-->
代码语言:txt复制
        <dependency>
代码语言:txt复制
            <groupId>mysql</groupId>
代码语言:txt复制
            <artifactId>mysql-connector-java</artifactId>
代码语言:txt复制
            <version>5.1.46</version>
代码语言:txt复制
        </dependency>
代码语言:txt复制
        <!--junit 单元测试-->
代码语言:txt复制
        <dependency>
代码语言:txt复制
            <groupId>junit</groupId>
代码语言:txt复制
            <artifactId>junit</artifactId>
代码语言:txt复制
            <version>4.13</version>
代码语言:txt复制
            <scope>test</scope>
代码语言:txt复制
        </dependency>
代码语言:txt复制
        <!-- 添加slf4j日志api -->
代码语言:txt复制
        <dependency>
代码语言:txt复制
            <groupId>org.slf4j</groupId>
代码语言:txt复制
            <artifactId>slf4j-api</artifactId>
代码语言:txt复制
            <version>1.7.20</version>
代码语言:txt复制
        </dependency>
代码语言:txt复制
        <!-- 添加logback-classic依赖 -->
代码语言:txt复制
        <dependency>
代码语言:txt复制
            <groupId>ch.qos.logback</groupId>
代码语言:txt复制
            <artifactId>logback-classic</artifactId>
代码语言:txt复制
            <version>1.2.3</version>
代码语言:txt复制
        </dependency>
代码语言:txt复制
        <!-- 添加logback-core依赖 -->
代码语言:txt复制
        <dependency>
代码语言:txt复制
            <groupId>ch.qos.logback</groupId>
代码语言:txt复制
            <artifactId>logback-core</artifactId>
代码语言:txt复制
            <version>1.2.3</version>
代码语言:txt复制
        </dependency>
代码语言:txt复制
        <!--解决报错:Failed to load class “org.slf4j.impl.StaticLoggerBinder-->
代码语言:txt复制
        <dependency>
代码语言:txt复制
            <groupId>org.slf4j</groupId>
代码语言:txt复制
            <artifactId>slf4j-nop</artifactId>
代码语言:txt复制
            <version>1.7.5</version>
代码语言:txt复制
        </dependency>
代码语言:txt复制
    </dependencies>
代码语言:txt复制
</project>
代码语言:txt复制
```
  • logback.xml ```xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- CONSOLE :表示当前的日志信息是可以输出到控制台的。 --> <appender name="Console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n</pattern> </encoder> </appender>
代码语言:txt复制
    <logger name="com.ruochen" level="DEBUG" additivity="false">
代码语言:txt复制
        <appender-ref ref="Console"/>
代码语言:txt复制
    </logger>
代码语言:txt复制
    <!--
代码语言:txt复制
      level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
代码语言:txt复制
     , 默认debug
代码语言:txt复制
      <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
代码语言:txt复制
      -->
代码语言:txt复制
    <root level="DEBUG">
代码语言:txt复制
        <appender-ref ref="Console"/>
代码语言:txt复制
    </root>
代码语言:txt复制
</configuration>
代码语言:txt复制
```
  • mybatis.config.xml ```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?useSSl=false"/> <property name="username" value="root"/> <property name="password" value="ruochen666"/> </dataSource> </environment> </environments> <mappers> <!--加载sql映射文件--> <mapper resource="com/ruochen/mapper/UserMapper.xml"/> </mappers> </configuration> ```
  • UserMapper.xml ```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">
代码语言:txt复制
<!--
代码语言:txt复制
    namespace:名称空间
代码语言:txt复制
-->
代码语言:txt复制
<mapper namespace="com.ruochen.mapper.UserMapper">
代码语言:txt复制
    <select id="selectAll" resultType="com.ruochen.pojo.User">
代码语言:txt复制
        select * from tb_user;
代码语言:txt复制
    </select>
代码语言:txt复制
</mapper>
代码语言:txt复制
```
  • MyBatisDemo.java ```java package com.ruochen;
代码语言:txt复制
import com.ruochen.pojo.User;
代码语言:txt复制
import org.apache.ibatis.io.Resources;
代码语言:txt复制
import org.apache.ibatis.session.SqlSession;
代码语言:txt复制
import org.apache.ibatis.session.SqlSessionFactory;
代码语言:txt复制
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
代码语言:txt复制
import java.io.IOException;
代码语言:txt复制
import java.io.InputStream;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
/**
代码语言:txt复制
 * MyBatis 快速入门代码
 */
public class MyBatisDemo {
代码语言:txt复制
    public static void main(String[] args) throws IOException {
代码语言:txt复制
        // 1. 加载 MyBatis 的核心配置文件,获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取 SqlSession 对象,用它来执行 sql
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 执行 sql 语句
代码语言:txt复制
        List<User> users = sqlSession.selectList("test.selectAll");
代码语言:txt复制
        System.out.println(users);
代码语言:txt复制
        // 4. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
}
代码语言:txt复制
```
代码语言:txt复制
	[User{id=1, username='zhangsan', password='123', gender='男', addr='北京'}, User{id=2, username='李四', password='234', gender='女', addr='天津'}, User{id=3, username='王五', password='11', gender='男', addr='西安'}, User{id=4, username='赵六', password='111', gender='女', addr='上海'}]

Mapper 代理

  • 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
  • 设置SQL映射文件的namespace属性为Mapper接口全限定名
  • 在 Mapper 接口中定义方法,方法名就是SQL映射文件中SQL语句的id,并保持参数类型和返回值类型一致 ```java package com.ruochen.mapper;
代码语言:txt复制
import com.ruochen.pojo.User;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
public interface UserMapper {
代码语言:txt复制
    List<User> selectAll();
代码语言:txt复制
}
代码语言:txt复制
```
  • 编码测试 ```java package com.ruochen;
代码语言:txt复制
import com.ruochen.mapper.UserMapper;
代码语言:txt复制
import com.ruochen.pojo.User;
代码语言:txt复制
import org.apache.ibatis.io.Resources;
代码语言:txt复制
import org.apache.ibatis.session.SqlSession;
代码语言:txt复制
import org.apache.ibatis.session.SqlSessionFactory;
代码语言:txt复制
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
代码语言:txt复制
import java.io.IOException;
代码语言:txt复制
import java.io.InputStream;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
/**
代码语言:txt复制
 * Mapper 代理开发
 */
public class MyBatisDemo2 {
代码语言:txt复制
    public static void main(String[] args) throws IOException {
代码语言:txt复制
        // 1. 加载 MyBatis 的核心配置文件,获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取 SqlSession 对象,用它来执行 sql
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 执行 sql 语句
代码语言:txt复制
        // List<User> users = sqlSession.selectList("test.selectAll");
代码语言:txt复制
        // 3.1 获取 UserMapper 接口的代理对象
代码语言:txt复制
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
代码语言:txt复制
        List<User> users = userMapper.selectAll();
代码语言:txt复制
        System.out.println(users);
代码语言:txt复制
        // 4. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
}
代码语言:txt复制
```
代码语言:txt复制
	[User{id=1, username='zhangsan', password='123', gender='男', addr='北京'}, User{id=2, username='李四', password='234', gender='女', addr='天津'}, User{id=3, username='王五', password='11', gender='男', addr='西安'}, User{id=4, username='赵六', password='111', gender='女', addr='上海'}]

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

案例 - 配置文件完成增删改查

准备工作

  • 数据库表:tb_brand.sql ```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);
代码语言:txt复制
SELECT * FROM tb_brand;
代码语言:txt复制
```
  • 实体类:Brand.java ```java package com.ruochen.pojo;
代码语言:txt复制
/**
代码语言:txt复制
 * 品牌
 *
 * alt   鼠标左键:整列编辑
 *
 * 在实体类中,基本数据类型建议使用其对应的包装类型
 */
代码语言:txt复制
public class Brand {
代码语言:txt复制
    // id 主键
代码语言:txt复制
    private Integer id;
代码语言:txt复制
    // 品牌名称
代码语言:txt复制
    private String brandName;
代码语言:txt复制
    // 企业名称
代码语言:txt复制
    private String companyName;
代码语言:txt复制
    // 排序字段
代码语言:txt复制
    private Integer ordered;
代码语言:txt复制
    // 描述信息
代码语言:txt复制
    private String description;
代码语言:txt复制
    // 状态:0:禁用  1:启用
代码语言:txt复制
    private Integer status;
代码语言:txt复制
    public Integer getId() {
代码语言:txt复制
        return id;
代码语言:txt复制
    }
代码语言:txt复制
    public void setId(Integer id) {
代码语言:txt复制
        this.id = id;
代码语言:txt复制
    }
代码语言:txt复制
    public String getBrandName() {
代码语言:txt复制
        return brandName;
代码语言:txt复制
    }
代码语言:txt复制
    public void setBrandName(String brandName) {
代码语言:txt复制
        this.brandName = brandName;
代码语言:txt复制
    }
代码语言:txt复制
    public String getCompanyName() {
代码语言:txt复制
        return companyName;
代码语言:txt复制
    }
代码语言:txt复制
    public void setCompanyName(String companyName) {
代码语言:txt复制
        this.companyName = companyName;
代码语言:txt复制
    }
代码语言:txt复制
    public Integer getOrdered() {
代码语言:txt复制
        return ordered;
代码语言:txt复制
    }
代码语言:txt复制
    public void setOrdered(Integer ordered) {
代码语言:txt复制
        this.ordered = ordered;
代码语言:txt复制
    }
代码语言:txt复制
    public String getDescription() {
代码语言:txt复制
        return description;
代码语言:txt复制
    }
代码语言:txt复制
    public void setDescription(String description) {
代码语言:txt复制
        this.description = description;
代码语言:txt复制
    }
代码语言:txt复制
    public Integer getStatus() {
代码语言:txt复制
        return status;
代码语言:txt复制
    }
代码语言:txt复制
    public void setStatus(Integer status) {
代码语言:txt复制
        this.status = status;
代码语言:txt复制
    }
代码语言:txt复制
    @Override
代码语言:txt复制
    public String toString() {
代码语言:txt复制
        return "Brand{"  
代码语言:txt复制
                "id="   id  
代码语言:txt复制
                ", brandName='"   brandName   '''  
代码语言:txt复制
                ", companyName='"   companyName   '''  
代码语言:txt复制
                ", ordered="   ordered  
代码语言:txt复制
                ", description='"   description   '''  
代码语言:txt复制
                ", status="   status  
代码语言:txt复制
                '}';
代码语言:txt复制
    }
代码语言:txt复制
}
代码语言:txt复制
```
  • 测试用例:test 中新建 com.ruochen.test.MyBatisTest.java
  • 安装 MyBatisX 插件 - XML 和 接口方法 相互跳转 - 根据接口方法生成 statement 查询1. 查询所有数据
  • 编写接口方法:Mapper接口 - 参数:无 - 结果:List<Brand> ```java package com.ruochen.mapper;
代码语言:txt复制
import com.ruochen.pojo.Brand;
代码语言:txt复制
import java.util.List;
代码语言:txt复制
public interface BrandMapper {
代码语言:txt复制
    /**
代码语言:txt复制
     * 查询所有
     */
    public List<Brand> selectAll();
}
```编写 SQL 语句:SQL映射文件	```xml
	    <select id="selectAll" resultType="brand">
	        select *
	        from tb_brand;
	    </select>
	```执行方法,测试	```java
	    @Test
	    public void TestSelectAll() throws IOException {
	        // 1. 获取 SqlSessionFactory
	        String resource = "mybatis-config.xml";
	        InputStream inputStream = Resources.getResourceAsStream(resource);
	        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象 
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
        List<Brand> brands = brandMapper.selectAll();
代码语言:txt复制
        System.out.println(brands);
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```

数据库的字段名称和实体类的属性名称不一样,则不能自动封装数据

起别名:对不一样的列名起别名,让别名和实体类的属性名一样

- 缺点:每次查询都要定义一次别名

- 解决方案:可以使用sql 片段(缺点:不灵活)

在这里插入图片描述在这里插入图片描述

resultMap

- 定义 <resultMap> 标签

- 在 <select> 标签中,使用 resultMap 属性替换 resultType 属性在这里插入图片描述在这里插入图片描述

2. 根据Id查询
  • 编写接口方法:Mapper接口 - 参数:id - 结果:Brand ```java /** * 查看详情:根据Id查询 */ Brand selectById(int id); ```
  • 编写 SQL 语句:SQL映射文件 ```xml <select id="selectById" resultMap="brandResultMap"> select * from tb_brand where id = #{id}; </select> ```
  • 执行方法,测试 ```java @Test public void TestSelectById() throws IOException { // 接收参数 int id = 1;
代码语言:txt复制
        // 1. 获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
        Brand brand = brandMapper.selectById(id);
代码语言:txt复制
        System.out.println(brand);
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```

参数占位符:

- #{}:会将其替换为?,为了防止 SQL 注入

- ${}:拼接 SQL,会存在 SQL 注入问题

- 使用时机:

- 参数传递的时候:${}

- 表名或者列名不固定的情况:${}

 

参数类型:parameterType:可以省略

 

特殊字符处理:

转义字符:eg:< 对应 < CDATA区:<![CDATA[内容]]> 在这里插入图片描述在这里插入图片描述3. 多条件查询

  • 编写接口方法:Mapper接口 - 参数:所有查询条件 - 结果:List<Brand> ```java /** * 条件查询 * * 参数接收 * 1. 散装参数:如果方法中有多个参数,需要使用 @Param("SQL参数占位符名称") * 2. 对象参数:对象的属性的名称要和参数占位符名称一致 * 3. map集合参数 * * @param status * @param companyName * @param brandName * @return */ // List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
代码语言:txt复制
//    List<Brand> selectByCondition(Brand brand);
代码语言:txt复制
    List<Brand> selectByCondition(Map map);
代码语言:txt复制
```
  • 编写 SQL 语句:SQL 映射文件 ```xml <select id="selectByCondition" resultMap="brandResultMap"> select * from tb_brand where status = #{status} and company_name like #{companyName} and brand_name like #{brandName}; </select> ```
  • 执行方法,测试 ```java /** * 多条件查询 * @throws IOException */ @Test public void TestSelectByCondition() throws IOException { // 接收参数 int status = 1; String companyName = "华为"; String brandName = "华为";
代码语言:txt复制
        // 处理参数
代码语言:txt复制
        companyName = "%"   companyName   "%";
代码语言:txt复制
        brandName = "%"   brandName   "%";
代码语言:txt复制
        // 封装对象
代码语言:txt复制
//        Brand brand = new Brand();
代码语言:txt复制
//        brand.setStatus(status);
代码语言:txt复制
//        brand.setCompanyName(companyName);
代码语言:txt复制
//        brand.setBrandName(brandName);
代码语言:txt复制
        Map map = new HashMap();
代码语言:txt复制
        map.put("status", status);
代码语言:txt复制
        map.put("companyName", companyName);
代码语言:txt复制
        map.put("brandName", brandName);
代码语言:txt复制
        // 1. 获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
//        List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
代码语言:txt复制
//        List<Brand> brands = brandMapper.selectByCondition(brand);
代码语言:txt复制
        List<Brand> brands = brandMapper.selectByCondition(map);
代码语言:txt复制
        System.out.println(brands);
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```

中文查询不到结果可将 jdbc 修改为如下

<property name="url" value="jdbc:mysql:///mybatis?useSSl=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>

4. 多条件查询 - 动态条件查询
  • 修改 SQL 语句即可 ```xml <!-- 动态SQL * if:条件判断 * test:逻辑表达式 * 问题:第一个条件不满足时,SQL 语法错误 * 恒等式 where 后面加 1 = 1,条件都加上 and * <where> 替换 where 关键字 --> <select id="selectByCondition" resultMap="brandResultMap"> select * from tb_brand <!-- where --> <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> ```
5. 单条件查询 - 动态条件查询
  • Mapper 接口 ```java /** * 单条件动态查询 * @param brand * @return */ List<Brand> selectByConditionSingle(Brand brand);
代码语言:txt复制
```
  • SQL 映射文件 ```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 and companyName != ''"><!-- 相当于 case--> company_name like #{companyName} </when> <when test="brandName != null and brandName != ''"><!-- 相当于 case--> brand_name like #{brandName}; </when> <otherwise> <!-- 类似于 default --> 1 = 1 </otherwise> </choose> </select> ``` 可不使用 <otherwise>,使用 <where> 标签 ```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 and companyName != ''"><!-- 相当于 case--> company_name like #{companyName} </when> <when test="brandName != null and brandName != ''"><!-- 相当于 case--> brand_name like #{brandName}; </when> </choose> </where> </select> ```
  • 执行方法,测试 ```java /** * 单条件查询 * * @throws IOException */ @Test public void TestSelectByConditionSingle() throws IOException { // 接收参数 int status = 1; String companyName = "华为"; String brandName = "华为";
代码语言:txt复制
        // 处理参数
代码语言:txt复制
        companyName = "%"   companyName   "%";
代码语言:txt复制
        brandName = "%"   brandName   "%";
代码语言:txt复制
        // 封装对象
代码语言:txt复制
        Brand brand = new Brand();
代码语言:txt复制
        brand.setStatus(status);
代码语言:txt复制
//        brand.setCompanyName(companyName);
代码语言:txt复制
//        brand.setBrandName(brandName);
代码语言:txt复制
        // 1. 获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
        List<Brand> brands = brandMapper.selectByConditionSingle(brand);
代码语言:txt复制
        System.out.println(brands);
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```

添加

  • 编写接口方法:Mapper 接口 - 参数:除了 id 之外的所有数据 - 结果:void ```java /** * 添加 * @param brand */ void add(Brand brand); ```
  • 编写 SQL 语句:SQL 映射文件 ```xml <!-- 添加 --> <insert id="add"> insert into tb_brand (brand_name, company_name, ordered, description, status) values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status}); </insert> ```
  • 执行方法,测试 ```java /** * 添加 * * @throws IOException */ @Test public void TestAdd() throws IOException { // 接收参数 int status = 1; String companyName = "波导手机"; String brandName = "波导"; String description = "手机中的战斗机"; int ordered = 100;
代码语言:txt复制
        // 处理参数
代码语言:txt复制
        companyName = "%"   companyName   "%";
代码语言:txt复制
        brandName = "%"   brandName   "%";
代码语言:txt复制
        // 封装对象
代码语言:txt复制
        Brand brand = new Brand();
代码语言:txt复制
        brand.setStatus(status);
代码语言:txt复制
        brand.setCompanyName(companyName);
代码语言:txt复制
        brand.setBrandName(brandName);
代码语言:txt复制
        brand.setDescription(description);
代码语言:txt复制
        brand.setOrdered(ordered);
代码语言:txt复制
        // 1. 获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
        brandMapper.add(brand);
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```

运行后发现并没有添加到数据库中,这就要说到MyBatis的事务

添加 sqlSession.commit(); 即可

或者 SqlSession sqlSession = sqlSessionFactory.openSession(true); 设置为自动提交事务(关闭事务)

添加 - 主键返回

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

SQL 映射文件:<insert id="add" useGeneratedKeys="true" keyProperty="id">

测试文件中直接获取即可:Integer id = brand.getId();

修改

1. 修改全部字段
  • 编写接口方法:Mapper 接口 - 参数:所有数据 - 结果:void ```java /** * 修改 * @param brand * @return */ int update(Brand brand); ```
  • 编写 SQL 语句:SQL 映射文件 ```xml <!-- 修改 --> <update id="update"> update tb_brand set brand_name = #{brandName}, company_name= #{companyName}, ordered = #{ordered}, description = #{description}, status = #{status} where id = #{id}; </update> ```
  • 执行方法,测试 ```java /** * 修改 * * @throws IOException */ @Test public void TestUpdate() throws IOException { // 接收参数 int status = 1; String companyName = "波导手机"; String brandName = "波导"; String description = "波导手机,手机中的战斗机"; int ordered = 200; int id = 6;
代码语言:txt复制
        // 封装对象
代码语言:txt复制
        Brand brand = new Brand();
代码语言:txt复制
        brand.setStatus(status);
代码语言:txt复制
        brand.setCompanyName(companyName);
代码语言:txt复制
        brand.setBrandName(brandName);
代码语言:txt复制
        brand.setDescription(description);
代码语言:txt复制
        brand.setOrdered(ordered);
代码语言:txt复制
        brand.setId(id);
代码语言:txt复制
        // 1. 获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
        int count = brandMapper.update(brand);
代码语言:txt复制
        System.out.println(count);
代码语言:txt复制
        // 提交事务
代码语言:txt复制
         sqlSession.commit();
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```
2. 修改动态字段
  • 编写 SQL 语句:SQL 映射文件```xml <!-- 修改 - 动态修改 --> <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 stauts != ''"> status = #{status} </if> </set> where id = #{id}; </update> ```删除1. 删除一个
  • 编写接口方法:Mapper 接口 - 参数:id - 结果:void ```java /** * 根据Id 删除 * @param id */ void deleteById(int id); ```
  • 编写 SQL 语句:SQL 映射文件 ```xml <!-- 删除 - 删除一条 --> <delete id="deleteById"> delete from tb_brand where id = #{id}; </delete> ```
  • 执行方法,测试 ```java /** * 根据Id 删除 * * @throws IOException */ @Test public void TestDeleteById() throws IOException { // 接收参数 int id = 6;
代码语言:txt复制
        // 1. 获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
        brandMapper.deleteById(id);
代码语言:txt复制
        // 提交事务
代码语言:txt复制
        sqlSession.commit();
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```
2. 批量删除
  • 编写接口方法:Mapper 接口 - 参数:id数组 - 结果:void ```java /** * 批量删除 * @param ids */ void deleteByIds(@Param("ids") int[] ids); ```
  • 编写 SQL 语句:SQL 映射文件 ```xml <!-- 批量删除 MyBatis 会将数组参数,封装为一个 Map 集合 * 默认:array = 数组 * 使用 @Param 注解 改变 Map 集合的默认 key 的名称 -->
代码语言:txt复制
    <delete id="deleteByIds">
代码语言:txt复制
        delete from tb_brand where id in
代码语言:txt复制
        <foreach collection="ids" item="id" separator="," open="(" close=")">
代码语言:txt复制
            ${id}
代码语言:txt复制
        </foreach>
代码语言:txt复制
    </delete>
代码语言:txt复制
```
  • 执行方法,测试 ```java /** * 批量删除 * * @throws IOException */ @Test public void TestDeleteByIds() throws IOException { // 接收参数 int[] ids = {7, 8};
代码语言:txt复制
        // 1. 获取 SqlSessionFactory
代码语言:txt复制
        String resource = "mybatis-config.xml";
代码语言:txt复制
        InputStream inputStream = Resources.getResourceAsStream(resource);
代码语言:txt复制
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
代码语言:txt复制
        // 2. 获取SqlSession对象
代码语言:txt复制
        SqlSession sqlSession = sqlSessionFactory.openSession();
代码语言:txt复制
        // 3. 获取 Mapper 接口代理对象
代码语言:txt复制
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制
        // 4. 执行方法
代码语言:txt复制
        brandMapper.deleteByIds(ids);
代码语言:txt复制
        // 提交事务
代码语言:txt复制
        sqlSession.commit();
代码语言:txt复制
        // 5. 释放资源
代码语言:txt复制
        sqlSession.close();
代码语言:txt复制
    }
代码语言:txt复制
```

MyBatis 参数传递

  • MyBatis 提供了 ParamNameResolver 类来进行参数封装
  • 单个参数 - POJO类型:直接使用,属性名 和 参数占位符名称 一致 - Map集合:直接使用,键名 和 参数占位符名称 一致 - Collection:封装为 Map 集合,可以使用@Param注解,替换Map集合中默认的arg键名 ``` map.put("arg0", collection集合) map.put("collection", collection集合) ``` - List:封装为 Map 集合,可以使用@Param注解,替换Map集合中默认的arg键名 ``` map.put("arg0", list集合) map.put("collection", list集合) map.put("list", list集合) ``` - Array:封装为 Map 集合,可以使用@Param注解,替换Map集合中默认的arg键名 ``` map.put("array", 数组) map.put("arg0", 数组) ``` - 其他类型:直接使用
  • 多个参数:封装为 Map 集合,可以使用@Param注解,替换Map集合中默认的arg键名 ``` map.put("arg0", 参数值1) map.put("param1", 参数值1) map.put("arg1", 参数值2) map.put("param2", 参数值2) ---------------@Param("username") map.put("username", 参数值1) map.put("param1", 参数值1) map.put("arg1", 参数值2) map.put("param2", 参数值2) ```

注解完成增删改查

  • 查询:@Select
  • 添加:@Insert
  • 修改:@Update
  • 删除:@Delete
代码语言:java复制
@Select("select * from tb_user where id = #{id}")
public User selectById(int id);

【注】

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。

0 人点赞