前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MyBatis 详细教程

MyBatis 详细教程

原创
作者头像
ruochen
修改2022-03-08 10:25:29
2.1K0
修改2022-03-08 10:25:29
举报

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 的语句映射方式间自由移植和切换。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MyBatis
  • Mapper 代理
  • 案例 - 配置文件完成增删改查
    • 准备工作
      • 2. 根据Id查询
      • 4. 多条件查询 - 动态条件查询
      • 5. 单条件查询 - 动态条件查询
    • 添加
      • 修改
        • 1. 修改全部字段
        • 2. 修改动态字段
        • 2. 批量删除
      • MyBatis 参数传递
        • 注解完成增删改查
        相关产品与服务
        云数据库 SQL Server
        腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档