还在为学MyBatis发愁?史上最全,一篇文章带你学习MyBatis

文章目录

  • 前言
  • 一、📖MyBatis简介
    • 1.Mybatis历史
    • 2.MyBatis特性
    • 3.对比(其他持久化层技术)
  • 二、📣搭建MyBatis
    • 1.开发环境
    • 2.创建maven工程
    • 3.创建MyBatis核心配置文件
    • 4.创建mapper接口
    • 5.创建MyBatis的映射文件
    • 6.通过junit测试功能
    • 7.加入log4j日志功能
    • 8.核心配置文件详解
  • 三、📝MyBatis的增删改查(映射文件)
  • 四、📝MyBatis获取参数值的两种方式(重点)
    • 1.单个字面量类型的参数
    • 2.多个字面量类型的参数
    • 3.map集合类型的参数
    • 4.实体类类型的参数
    • 5.使用@Param标识参数
  • 五、📝MyBatis的各种查询功能
    • 1.查询一个实体类对象
    • 2.查询一个List集合
    • 3.查询单个数据
    • 4.查询一条数据为map集合
    • 5.查询多条数据为map集合
      • 方法一
      • 方法二
    • 6.测试类
  • 六、📣特殊SQL的执行
    • 1.模糊查询
    • 2.批量删除
    • 3.动态设置表名
    • 5.添加功能获取自增的主键
    • 6.测试类
  • 七、📣自定义映射resultMap
    • 1.resultMap处理字段和属性的映射关系
    • 2.多对一映射处理
      • 级联方式处理映射关系
      • 使用association处理映射关系
      • 分步查询
        • 1. 查询员工信息
        • 2. 查询部门信息
    • 3.一对多映射处理
      • collection
      • 分步查询
        • 1. 查询部门信息
        • 2. 根据部门id查询部门中的所有员工
    • 4.延迟加载
    • 5.测试类
  • 八、📣动态SQL
    • 1.if
    • 2.where
    • 3.trim
    • 4.choose、when、otherwise
    • 5.foreach
    • 6.SQL片段
    • 7.测试类
  • 总结


前言

从Mybatis搭建到各种配置和注解,带你快速学会MyBatis。


一、📖MyBatis简介

1.Mybatis历史

MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下,iBatis3.x正式更名为MyBatis。代码于2013年11月迁移到Github。
iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。

2.MyBatis特性

  • MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。
  • MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
  • MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
  • MyBatis 是一个 半自动的ORM(Object Relation Mapping)框架。

3.对比(其他持久化层技术)

  • JDBC
    • SQL 夹杂在Java代码中耦合度高,导致硬编码内伤
    • 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见
    • 代码冗长,开发效率低
  • Hibernate 和 JPA
    • 操作简便,开发效率高
    • 程序中的长难复杂 SQL 需要绕过框架
    • 内部自动生产的 SQL,不容易做特殊优化
    • 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。
    • 反射操作太多,导致数据库性能下降
  • MyBatis
    • 轻量级,性能出色
    • SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
    • 开发效率稍逊于HIbernate,但是完全能够接受

二、📣搭建MyBatis

1.开发环境

  • IDEA:idea 2022.3.3
  • 构建工具:maven 3.9.2
  • MySQL版本:MySQL 8.0
  • MyBatis版本:MyBatis 3.5.7

2.创建maven工程

<dependencies><!-- Mybatis核心 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><!-- junit测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency>
</dependencies>

3.创建MyBatis核心配置文件

习惯上命名为mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。将来整合Spring之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。
核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息。
核心配置文件存放的位置是src/main/resources目录下。

<?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.cj.jdbc.Driver"/>  <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>  <property name="username" value="root"/>  <property name="password" value="root"/>  </dataSource>  </environment>  </environments>  <!--引入映射文件-->  <mappers>  <mapper resource="mappers/UserMapper.xml"/>  </mappers>  
</configuration>

4.创建mapper接口

MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类

package com.atguigu.mybatis.mapper;  public interface UserMapper {  /**  * 添加用户信息  */  int insertUser();  
}

5.创建MyBatis的映射文件

  • 相关概念:ORM(Object Relationship Mapping)对象关系映射。
    • 对象:Java的实体类对象
    • 关系:关系型数据库
    • 映射:二者之间的对应关系
Java概念数据库概念
属性字段/列
对象记录/行
  • 映射文件的命名规则
    • 表所对应的实体类的类名+Mapper.xml
    • 例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml
    • 因此一个映射文件对应一个实体类,对应一张表的操作
    • MyBatis映射文件用于编写SQL,访问以及操作表中的数据
    • MyBatis映射文件存放的位置是src/main/resources/mappers目录下
  • MyBatis中可以面向接口操作数据,要保证两个一致
    • mapper接口的全类名和映射文件的命名空间(namespace)保持一致
    • mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致
      在这里插入图片描述
      上图中的目录名一样,请大家不要弄错。
<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper  
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">  <!--int insertUser();该方法就是UserMapper接口中的inserUser方法-->  <insert id="insertUser">  insert into t_user values(null,'张三','123',23,'女')  </insert>  
</mapper>

6.通过junit测试功能

依赖:

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency>

在test包下的java下创建测试类运行:
在这里插入图片描述

  • SqlSession:代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的会话)。
  • SqlSessionFactory:是“生产”SqlSession的“工厂”。
  • 工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类”中,以后都使用这个工厂类来“生产”我们需要的对象。
public class UserMapperTest {@Testpublic void testInsertUser() throws IOException {//读取MyBatis的核心配置文件InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//获取SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);//获取sqlSession,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务//SqlSession sqlSession = sqlSessionFactory.openSession();//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交  SqlSession sqlSession = sqlSessionFactory.openSession(true);//通过代理模式创建UserMapper接口的代理实现类对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句int result = userMapper.insertUser();//提交事务//sqlSession.commit();System.out.println("result:" + result);}
}
  • 此时需要手动提交事务,如果要自动提交事务,则在获取sqlSession对象时,使用SqlSession sqlSession = sqlSessionFactory.openSession(true);,传入一个Boolean类型的参数,值为true,这样就可以自动提交。

7.加入log4j日志功能

  1. 加入依赖
    <!-- log4j日志 -->
    <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
    </dependency>
    
  2. 加入log4j的配置文件
    • log4j的配置文件名为log4j.xml,存放的位置是src/main/resources目录下
    • 日志的级别:FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试) 从左到右打印的内容越来越详细
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><param name="Encoding" value="UTF-8" /><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /></layout></appender><logger name="java.sql"><level value="debug" /></logger><logger name="org.apache.ibatis"><level value="info" /></logger><root><level value="debug" /><appender-ref ref="STDOUT" /></root>
    </log4j:configuration>
    

如下图,加入日志打印在控制台可以看到sql语句,传入参数和影响行数。
在这里插入图片描述

8.核心配置文件详解

核心配置文件中的标签必须按照固定的顺序(有的标签可以不写,但顺序一定不能乱):
properties、settings、typeAliases、typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、plugins、environments、databaseIdProvider、mappers

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//MyBatis.org//DTD Config 3.0//EN""http://MyBatis.org/dtd/MyBatis-3-config.dtd">
<configuration><!--引入properties文件,此时就可以${属性名}的方式访问属性值--><properties resource="jdbc.properties"></properties><settings><!--将表中字段的下划线自动转换为驼峰--><setting name="mapUnderscoreToCamelCase" value="true"/><!--开启延迟加载--><setting name="lazyLoadingEnabled" value="true"/></settings><typeAliases><!--typeAlias:设置某个具体的类型的别名属性:type:需要设置别名的类型的全类名alias:设置此类型的别名,且别名不区分大小写。若不设置此属性,该类型拥有默认的别名,即类名--><!--<typeAlias type="com.dragon.mybatis.bean.User"></typeAlias>--><!--<typeAlias type="com.dragon.mybatis.bean.User" alias="user"></typeAlias>--><!--以包为单位,设置改包下所有的类型都拥有默认的别名,即类名且不区分大小写--><package name="com.dragon.mybatis.pojo"/></typeAliases><!--environments:设置多个连接数据库的环境属性:default:设置默认使用的环境的id--><environments default="mysql_test"><!--environment:设置具体的连接数据库的环境信息属性:id:设置环境的唯一标识,可通过environments标签中的default设置某一个环境的id,表示默认使用的环境--><environment id="mysql_test"><!--transactionManager:设置事务管理方式属性:type:设置事务管理方式,type="JDBC|MANAGED"type="JDBC":设置当前环境的事务管理都必须手动处理type="MANAGED":设置事务被管理,例如spring中的AOP--><transactionManager type="JDBC"/><!--dataSource:设置数据源属性:type:设置数据源的类型,type="POOLED|UNPOOLED|JNDI"type="POOLED":使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从缓存中直接获取,不需要重新创建type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建type="JNDI":调用上下文中的数据源--><dataSource type="POOLED"><!--设置驱动类的全类名--><property name="driver" value="${jdbc.driver}"/><!--设置连接数据库的连接地址--><property name="url" value="${jdbc.url}"/><!--设置连接数据库的用户名--><property name="username" value="${jdbc.username}"/><!--设置连接数据库的密码--><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!--引入映射文件--><mappers><!-- <mapper resource="UserMapper.xml"/> --><!--以包为单位,将包下所有的映射文件引入核心配置文件注意:1. 此方式必须保证mapper接口和mapper映射文件必须在相同的包下2. mapper接口要和mapper映射文件的名字一致--><package name="com.dragon.mybatis.mapper"/></mappers>
</configuration>

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

三、📝MyBatis的增删改查(映射文件)

  1. 添加
    <!--int insertUser();-->
    <insert id="insertUser">insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
    </insert>
    
  2. 删除
    <!--int deleteUser();-->
    <delete id="deleteUser">delete from t_user where id = 6
    </delete>
    
  3. 修改
    <!--int updateUser();-->
    <update id="updateUser">update t_user set username = '张三' where id = 5
    </update>
    
  4. 查询一个实体类对象
    <!--User getUserById();-->  
    <select id="getUserById" resultType="com.atguigu.mybatis.bean.User">  select * from t_user where id = 2  
    </select>
    
  5. 查询集合
    <!--List<User> getUserList();-->
    <select id="getUserList" resultType="com.atguigu.mybatis.bean.User">select * from t_user
    </select>
    

如果配置文件中引入映射是以包的方式,resultType的值直接可以是实体类名如:User/user均可。

<!--引入映射文件--><mappers><!-- <mapper resource="UserMapper.xml"/> --><!--以包为单位,将包下所有的映射文件引入核心配置文件注意:1. 此方式必须保证mapper接口和mapper映射文件必须在相同的包下2. mapper接口要和mapper映射文件的名字一致--><package name="com.atguigu.mybatis.mapper"/></mappers>

我把上述增删改查的测试类也给大家吧:

package com.dragon.mybatis.test;import com.dragon.mybatis.mapper.UserMapper;
import com.dragon.mybatis.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 org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class MyBatisTest {@Testpublic void testMyBatis() throws IOException {//读取MyBatis的核心配置文件InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//获取SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);//获取sqlSession,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务//SqlSession sqlSession = sqlSessionFactory.openSession();//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交SqlSession sqlSession = sqlSessionFactory.openSession(true);//通过代理模式创建UserMapper接口的代理实现类对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句int result = userMapper.insertUser();//提交事务
//        sqlSession.commit();System.out.println("result:" + result);}@Testpublic void testUpdate() throws IOException {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);SqlSession sqlSession = sqlSessionFactory.openSession(true);UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.updateUser();}@Testpublic void deleteUser() throws IOException {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);SqlSession sqlSession = sqlSessionFactory.openSession(true);UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.deleteUser();}@Testpublic void testCRUD() throws IOException {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);SqlSession sqlSession = sqlSessionFactory.openSession(true);UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = mapper.getUserById();System.out.println(user);}@Testpublic void testgetAllUser() throws IOException {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);SqlSession sqlSession = sqlSessionFactory.openSession(true);UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> list = mapper.getAllUser();list.forEach(user -> System.out.println(user));}
}
  • 注意:
    1. 查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射关系
      • resultType:自动映射,用于属性名和表中字段名一致的情况
      • resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况
    2. 当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值

四、📝MyBatis获取参数值的两种方式(重点)

  • MyBatis获取参数值的两种方式:${}和#{}
  • ${}的本质就是字符串拼接,#{}的本质就是占位符赋值
  • ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号

1.单个字面量类型的参数

  • 若mapper接口中的方法参数为单个的字面量类型,此时可以使用${}和#{}以任意的名称,可以不是username,可以是a,x等等,不需要和接口中的方法的参数名保持一致(最好见名识意)获取参数的值,注意${}需要手动加单引号
<!--User getUserByUsername(String username);-->
<select id="getUserByUsername" resultType="User">select * from t_user where username = #{username}
</select>
<!--User getUserByUsername(String username);-->
<select id="getUserByUsername" resultType="User">  select * from t_user where username = '${username}'  
</select>

2.多个字面量类型的参数

  • 若mapper接口中的方法参数为多个时,此时MyBatis会自动将这些参数放在一个map集合中
    1. 以arg0,arg1…为键,以参数为值;
    2. 以param1,param2…为键,以参数为值;
  • 因此只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号。
  • 使用arg或者param都行,要注意的是,arg是从arg0开始的,param是从param1开始的
<!--User checkLogin(String username,String password);-->
<select id="checkLogin" resultType="User">  select * from t_user where username = #{arg0} and password = #{arg1}  
</select>
<!--User checkLogin(String username,String password);-->
<select id="checkLogin" resultType="User">select * from t_user where username = '${param1}' and password = '${param2}'
</select>
<!--User checkLogin(String username,String password);-->
<select id="checkLogin" resultType="User">select * from t_user where username = '${arg0}' and password = '${param2}'
</select>

上诉可以看出这四个参数是可以混用的。

3.map集合类型的参数

  • 若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在map中只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号
<!--User checkLoginByMap(Map<String,Object> map);-->
<select id="checkLoginByMap" resultType="User">select * from t_user where username = #{username} and password = #{password}
</select>
@Test
public void checkLoginByMap() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);Map<String,Object> map = new HashMap<>();map.put("usermane","admin");map.put("password","123456");User user = mapper.checkLoginByMap(map);System.out.println(user);
}

4.实体类类型的参数

  • 若mapper接口中的方法参数为实体类对象时此时可以使用${}和#{},通过访问实体类对象中的属性名获取属性值,注意${}需要手动加单引号
<!--int insertUser(User user);-->
<insert id="insertUser">insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
</insert>
@Test
public void insertUser() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);User user = new User(null,"Tom","123456",12,"男","123@321.com");mapper.insertUser(user);
}

5.使用@Param标识参数

  • 可以通过@Param注解标识mapper接口中的方法参数,此时,会将这些参数放在map集合中
    1. 以@Param注解的value属性值为键,以参数为值;
    2. 以param1,param2…为键,以参数为值;
  • 只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号
<!--User CheckLoginByParam(@Param("username") String username, @Param("password") String password);--><select id="CheckLoginByParam" resultType="User">select * from t_user where username = #{username} and password = #{password}</select>
@Test
public void checkLoginByParam() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);mapper.CheckLoginByParam("admin","123456");
}

五、📝MyBatis的各种查询功能

  1. 如果查询出的数据只有一条,可以通过
    • 实体类对象接收
    • List集合接收
    • Map集合接收,结果{password=123456, sex=男, id=1, age=23, username=admin}
  2. 如果查询出的数据有多条,一定不能用实体类对象接收,会抛异常TooManyResultsException,可以通过
    • 实体类类型的LIst集合接收
    • Map类型的LIst集合接收
    • 在mapper接口的方法上添加@MapKey注解

1.查询一个实体类对象

/*** 根据用户id查询用户信息* @param id* @return*/
User getUserById(@Param("id") int id);
<!--User getUserById(@Param("id") int id);-->
<select id="getUserById" resultType="User">select * from t_user where id = #{id}
</select>

2.查询一个List集合

/*** 查询所有用户信息* @return*/
List<User> getUserList();
<!--List<User> getUserList();-->
<select id="getUserList" resultType="User">select * from t_user
</select>

3.查询单个数据

/**  * 查询用户的总记录数  * @return  * 在MyBatis中,对于Java中常用的类型都设置了类型别名  * 例如:java.lang.Integer-->int|integer  * 例如:int-->_int|_integer  * 例如:Map-->map,List-->list  */  
int getCount();
<!--int getCount();-->
<select id="getCount" resultType="_integer">select count(id) from t_user
</select>

4.查询一条数据为map集合

/**  * 根据用户id查询用户信息为map集合  * @param id  * @return  */  
Map<String, Object> getUserToMap(@Param("id") int id);
<!--Map<String, Object> getUserToMap(@Param("id") int id);-->
<select id="getUserToMap" resultType="map">select * from t_user where id = #{id}
</select>
<!--结果:{password=123456, sex=男, id=1, age=23, username=admin}-->

5.查询多条数据为map集合

方法一

/**  * 查询所有用户信息为map集合  * @return  * 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此时可以将这些map放在一个list集合中获取  */  
List<Map<String, Object>> getAllUserToMap1();
<!--Map<String, Object> getAllUserToMap1();-->  
<select id="getAllUserToMap" resultType="map">  select * from t_user  
</select>
<!--结果:[{password=123456, sex=男, id=1, age=23, username=admin},{password=123456, sex=男, id=2, age=23, username=张三},{password=123456, sex=男, id=3, age=23, username=张三}]
-->

方法二

/*** 查询所有用户信息为map集合* @return* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的map集合*/
@MapKey("id")
Map<String, Object> getAllUserToMap2();
<!--Map<String, Object> getAllUserToMap2();-->
<select id="getAllUserToMap" resultType="map">select * from t_user
</select>
<!--结果:{1={password=123456, sex=男, id=1, age=23, username=admin},2={password=123456, sex=男, id=2, age=23, username=张三},3={password=123456, sex=男, id=3, age=23, username=张三}}
-->

6.测试类

package com.dragon.mybatis.test;import com.dragon.mybatis.mapper.SelectMapper;
import com.dragon.mybatis.pojo.User;
import com.dragon.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class SelectMapperTest {@Testpublic void testGetUserById(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);System.out.println(mapper.getUserById(3));}@Testpublic void testGetAllUser(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);List<User> users=mapper.getAllUser();users.forEach(user -> System.out.println(user));}@Testpublic void testGetCount(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);System.out.println(mapper.getCount());}@Testpublic void testGetUserToMap(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);System.out.println(mapper.getUserToMap(3));}@Testpublic void testAllUserToMap1(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);System.out.println(mapper.getAllUserToMap1());}@Testpublic void testAllUserToMap2(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);System.out.println(mapper.getAllUserToMap2());}
}

六、📣特殊SQL的执行

1.模糊查询

/*** 根据用户名进行模糊查询* @param username * @return java.util.List<com.atguigu.mybatis.pojo.User>* @date 2023/8/26 21:56*/
List<User> getUserByLike(@Param("username") String username);
<!--List<User> getUserByLike(@Param("username") String username);-->
<select id="getUserByLike" resultType="User"><!--select * from t_user where username like '%${username}%'-->  <!--select * from t_user where username like concat('%',#{username},'%')-->  select * from t_user where username like "%"#{username}"%"
</select>
  • 其中select * from t_user where username like "%"#{username}"%"是最常用的

2.批量删除

  • 只能使用${},如果使用#{},则解析后的sql语句为delete from t_user where id in ('1,2,3'),这样是将1,2,3看做是一个整体,只有id为1,2,3的数据会被删除。正确的语句应该是delete from t_user where id in (1,2,3),或者delete from t_user where id in ('1','2','3')
/*** 根据id批量删除* @param ids * @return int* @date 2023/8/26 22:06*/
int deleteMore(@Param("ids") String ids);
<delete id="deleteMore">delete from t_user where id in (${ids})
</delete>
//测试类
@Test
public void deleteMore() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);int result = mapper.deleteMore("1,2,3,8");System.out.println(result);
}

3.动态设置表名

  • 只能使用${},因为表名不能加单引号
/*** 查询指定表中的数据* @param tableName * @return java.util.List<com.atguigu.mybatis.pojo.User>* @date 2023/8/27 14:41*/
List<User> getUserByTable(@Param("tableName") String tableName);
<!--List<User> getUserByTable(@Param("tableName") String tableName);-->
<select id="getUserByTable" resultType="User">select * from ${tableName}
</select>

5.添加功能获取自增的主键

  • 使用场景
    • t_clazz(clazz_id,clazz_name)
    • t_student(student_id,student_name,clazz_id)
    1. 添加班级信息
    2. 获取新添加的班级的id
    3. 为班级分配学生,即将某学的班级id修改为新添加的班级的id
  • 在mapper.xml中设置两个属性
    • useGeneratedKeys:设置使用自增的主键
    • keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
/*** 添加用户信息* @param user * @date 2023/8/27 15:04*/
void insertUser(User user);
<!--void insertUser(User user);-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">insert into t_user values (null,#{username},#{password},#{age},#{sex},#{email})
</insert>

6.测试类

package com.dragon.mybatis.test;import com.dragon.mybatis.mapper.SQLMapper;
import com.dragon.mybatis.pojo.User;
import com.dragon.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class SQLMapperTest {@Testpublic void testUserByLike(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);List<User> list = mapper.getUserByLike("a");System.out.println(list);}@Testpublic void testDeleteMore(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);int result = mapper.deleteMore("1,2,3");System.out.println(result);}@Testpublic void testGetUserByTable(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);List<User> list= mapper.getUserByTable("t_user");System.out.println(list);}@Testpublic void insertUser() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);User user = new User(null, "ton", "123", 23, "男", "123@321.com");mapper.insertUser(user);System.out.println(user);//输出:user{id=10, username='ton', password='123', age=23, sex='男', email='123@321.com'},自增主键存放到了user的id属性中}
}

七、📣自定义映射resultMap

1.resultMap处理字段和属性的映射关系

  • resultMap:设置自定义映射
    • 属性:
      • id:表示自定义映射的唯一标识,不能重复
      • type:查询的数据要映射的实体类的类型
    • 子标签:
      • id:设置主键的映射关系
      • result:设置普通字段的映射关系
      • 子标签属性:
        • property:设置映射关系中实体类中的属性名
        • column:设置映射关系中表中的字段名
  • 若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来
<resultMap id="empResultMap" type="Emp"><id property="eid" column="eid"></id><result property="empName" column="emp_name"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="email" column="email"></result>
</resultMap>
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">select * from t_emp
</select>
  • 若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)。此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系
    1. 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
      <!--List<Emp> getAllEmp();-->
      <select id="getAllEmp" resultType="Emp">select eid,emp_name empName,age,sex,email from t_emp
      </select>
      
    2. 可以在MyBatis的核心配置文件中的setting标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。
    <settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings>

2.多对一映射处理

查询员工信息以及员工所对应的部门信息

public class Emp {  private Integer eid;  private String empName;  private Integer age;  private String sex;  private String email;  private Dept dept;//...构造器、get、set方法等
}

级联方式处理映射关系

<resultMap id="empAndDeptResultMapOne" type="Emp"><id property="eid" column="eid"></id><result property="empName" column="emp_name"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="email" column="email"></result><result property="dept.did" column="did"></result><result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>

使用association处理映射关系

  • association:处理多对一的映射关系
  • property:需要处理多对的映射关系的属性名
  • javaType:该属性的类型
<resultMap id="empAndDeptResultMapTwo" type="Emp"><id property="eid" column="eid"></id><result property="empName" column="emp_name"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="email" column="email"></result><association property="dept" javaType="Dept"><id property="did" column="did"></id><result property="deptName" column="dept_name"></result></association>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>

分步查询

1. 查询员工信息
  • select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
  • column:设置分步查询的条件
//EmpMapper里的方法
/*** 通过分步查询,员工及所对应的部门信息* 分步查询第一步:查询员工信息* @param  * @return com.dragon.mybatis.pojo.Emp* @date 2022/2/27 20:17*/
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
<resultMap id="empAndDeptByStepResultMap" type="Emp"><id property="eid" column="eid"></id><result property="empName" column="emp_name"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="email" column="email"></result><association property="dept"select="com.dragon.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"column="did"></association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">select * from t_emp where eid = #{eid}
</select>
2. 查询部门信息
//DeptMapper里的方法
/*** 通过分步查询,员工及所对应的部门信息* 分步查询第二步:通过did查询员工对应的部门信息* @param* @return com.dragon.mybatis.pojo.Emp* @date 2022/2/27 20:23*/
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
<!--此处的resultMap仅是处理字段和属性的映射关系-->
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept"><id property="did" column="did"></id><result property="deptName" column="dept_name"></result>
</resultMap>
<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">select * from t_dept where did = #{did}
</select>

3.一对多映射处理

public class Dept {private Integer did;private String deptName;private List<Emp> emps;//...构造器、get、set方法等
}

collection

  • collection:用来处理一对多的映射关系
  • ofType:表示该属性对饮的集合中存储的数据的类型
<resultMap id="DeptAndEmpResultMap" type="Dept"><id property="did" column="did"></id><result property="deptName" column="dept_name"></result><collection property="emps" ofType="Emp"><id property="eid" column="eid"></id><result property="empName" column="emp_name"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="email" column="email"></result></collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>

分步查询

1. 查询部门信息
//DeptMapper
/*** 通过分步查询,查询部门及对应的所有员工信息* 分步查询第一步:查询部门信息* @param did * @return com.dragon.mybatis.pojo.Dept* @date 2023/8/27 22:04*/
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept"><id property="did" column="did"></id><result property="deptName" column="dept_name"></result><collection property="emps"select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"column="did"></collection>
</resultMap>
<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">select * from t_dept where did = #{did}
</select>
2. 根据部门id查询部门中的所有员工
//EmpMapper
/*** 通过分步查询,查询部门及对应的所有员工信息* 分步查询第二步:根据部门id查询部门中的所有员工* @param did* @return java.util.List<com.atguigu.mybatis.pojo.Emp>* @date 2023/8/27 22:10*/
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">select * from t_emp where did = #{did}
</select>

4.延迟加载

  • 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
    • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
    • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载
  • 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)”
<settings><!--开启延迟加载--><setting name="lazyLoadingEnabled" value="true"/>
</settings>
@Test
public void getEmpAndDeptByStepOne() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp emp = mapper.getEmpAndDeptByStepOne(1);System.out.println(emp.getEmpName());
}
  • 关闭延迟加载,两条SQL语句都运行了
    在这里插入图片描述

  • 开启延迟加载,只运行获取emp的SQL语句
    在这里插入图片描述

@Test
public void getEmpAndDeptByStepOne() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp emp = mapper.getEmpAndDeptByStepOne(1);System.out.println(emp.getEmpName());System.out.println("----------------");System.out.println(emp.getDept());
}
  • 开启后,需要用到查询dept的时候才会调用相应的SQL语句
    在这里插入图片描述

  • fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载)|eager(立即加载)”

    <resultMap id="empAndDeptByStepResultMap" type="Emp"><id property="eid" column="eid"></id><result property="empName" column="emp_name"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="email" column="email"></result><association property="dept"select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"column="did"fetchType="lazy"></association>
    </resultMap>
    

5.测试类

import com.dragon.mybatis.mapper.DeptMapper;
import com.dragon.mybatis.mapper.EmpMapper;
import com.dragon.mybatis.pojo.Dept;
import com.dragon.mybatis.pojo.Emp;
import com.dragon.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class ResultMapTest {@Testpublic void testGetAllEmp(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);List<Emp> list = mapper.getAllEmp();System.out.println(list);}@Testpublic void testGetAndDept(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp emp = mapper.getEmpAndDept(1);System.out.println(emp);}@Testpublic void testGetAndDeptByStep(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);Emp emp = mapper.getEmpAndDeptByStepOne(1);System.out.println(emp);}@Testpublic void testGetDeptAndEmp(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);Dept dept = mapper.getDeptAndEmp(1);System.out.println(dept);}@Testpublic void testGetDeptAndEmpByStep(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);Dept dept = mapper.getDeptAndEmpByStepOne(1);System.out.println(dept);}
}

八、📣动态SQL

  • Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题

1.if

  • if标签可通过test属性(即传递过来的数据)的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
  • 在where后面添加一个恒成立条件1=1
    • 这个恒成立条件并不会影响查询的结果
    • 这个1=1可以用来拼接and语句,例如:当empName为null时
      • 如果不加上恒成立条件,则SQL语句为select * from t_emp where and age = ? and sex = ? and email = ?,此时where会与and连用,SQL语句会报错
      • 如果加上一个恒成立条件,则SQL语句为select * from t_emp where 1= 1 and age = ? and sex = ? and email = ?,此时不报错
<!--List<Emp> getEmpByCondition1(Emp emp);-->
<select id="getEmpByCondition1" resultType="Emp">select * from t_emp where 1=1<if test="empName != null and empName !=''">and emp_name = #{empName}</if><if test="age != null and age !=''">and age = #{age}</if><if test="sex != null and sex !=''">and sex = #{sex}</if><if test="email != null and email !=''">and email = #{email}</if>
</select>

2.where

  • where和if一般结合使用:
    • 若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
    • 若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and/or去掉
<!--List<Emp> getEmpByCondition2(Emp emp);-->
<select id="getEmpByCondition2" resultType="Emp">select * from t_emp<where><if test="empName != null and empName !=''">emp_name = #{empName}</if><if test="age != null and age !=''">and age = #{age}</if><if test="sex != null and sex !=''">and sex = #{sex}</if><if test="email != null and email !=''">and email = #{email}</if></where>
</select>
  • 注意:where标签不能去掉条件后多余的and/or
    <!--这种用法是错误的,只能去掉条件前面的and/or,条件后面的不行-->
    <if test="empName != null and empName !=''">
    emp_name = #{empName} and
    </if>
    <if test="age != null and age !=''">age = #{age}
    </if>
    

3.trim

  • trim用于去掉或添加标签中的内容
  • 常用属性
    • prefix:在trim标签中的内容的前面添加某些内容
    • suffix:在trim标签中的内容的后面添加某些内容
    • prefixOverrides:在trim标签中的内容的前面去掉某些内容
    • suffixOverrides:在trim标签中的内容的后面去掉某些内容
  • 若trim中的标签都不满足条件,则trim标签没有任何效果,也就是只剩下select * from t_emp
<!--List<Emp> getEmpByCondition3(Emp emp);-->
<select id="getEmpByCondition3" resultType="Emp">select * from t_emp<trim prefix="where" suffixOverrides="and|or"><if test="empName != null and empName !=''">emp_name = #{empName} and</if><if test="age != null and age !=''">age = #{age} and</if><if test="sex != null and sex !=''">sex = #{sex} or</if><if test="email != null and email !=''">email = #{email}</if></trim>
</select>

在这里插入图片描述

4.choose、when、otherwise

  • choose、when、otherwise相当于if...else if..else
  • when至少要有一个,otherwise至多只有一个
<select id="getEmpByChoose" resultType="Emp">select * from t_emp<where><choose><when test="empName != null and empName != ''">emp_name = #{empName}</when><when test="age != null and age != ''">age = #{age}</when><when test="sex != null and sex != ''">sex = #{sex}</when><when test="email != null and email != ''">email = #{email}</when><otherwise>did = 1</otherwise></choose></where>
</select>
@Test
public void getEmpByChoose() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);List<Emp> emps = mapper.getEmpByChoose(new Emp(null, "张三", 23, "男", "123@qq.com", null));System.out.println(emps);
}

在这里插入图片描述

  • 相当于if a else if b else if c else d,只会执行其中一个

5.foreach

  • 属性:

    • collection:设置要循环的数组或集合
    • item:表示集合或数组中的每一个数据
    • separator:设置循环体之间的分隔符,分隔符前后默认有一个空格,如,
    • open:设置foreach标签中的内容的开始符
    • close:设置foreach标签中的内容的结束符
  • 批量删除

    <!--int deleteMoreByArray(Integer[] eids);-->
    <delete id="deleteMoreByArray">delete from t_emp where eid in<foreach collection="eids" item="eid" separator="," open="(" close=")">#{eid}</foreach>
    </delete>
    
    @Test
    public void deleteMoreByArray() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);int result = mapper.deleteMoreByArray(new Integer[]{6, 7, 8, 9});System.out.println(result);
    }
    

    在这里插入图片描述

  • 批量添加

    <!--int insertMoreByList(@Param("emps") List<Emp> emps);-->
    <insert id="insertMoreByList">insert into t_emp values<foreach collection="emps" item="emp" separator=",">(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)</foreach>
    </insert>
    
    @Test
    public void insertMoreByList() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);Emp emp1 = new Emp(null,"a",1,"男","123@321.com",null);Emp emp2 = new Emp(null,"b",1,"男","123@321.com",null);Emp emp3 = new Emp(null,"c",1,"男","123@321.com",null);List<Emp> emps = Arrays.asList(emp1, emp2, emp3);int result = mapper.insertMoreByList(emps);System.out.println(result);
    }
    

    在这里插入图片描述

6.SQL片段

  • sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入
  • 声明sql片段:<sql>标签
<sql id="empColumns">eid,emp_name,age,sex,email</sql>
  • 引用sql片段:<include>标签
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">select <include refid="empColumns"></include> from t_emp
</select>

7.测试类

import com.dragon.mybatis.mapper.DynamicSQLMapper;
import com.dragon.mybatis.pojo.Emp;
import com.dragon.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.Arrays;
import java.util.List;public class DynamicSQLMapperTest {@Testpublic void testGetEmpByCondition1(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);List<Emp> list = mapper.getEmpByCondition1(new Emp(null,"张三",23,"男","123@qq.com",null));System.out.println(list);}@Testpublic void testGetEmpByCondition2(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);List<Emp> list = mapper.getEmpByCondition2(new Emp(null,"",23,"男","123@qq.com",null));System.out.println(list);}@Testpublic void testGetEmpByCondition3(){SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);List<Emp> list = mapper.getEmpByCondition3(new Emp(null,"",null,"","",null));System.out.println(list);}@Testpublic void getEmpByChoose() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);List<Emp> emps = mapper.getEmpByChoose(new Emp(null, "张三", 23, "男", "123@qq.com", null));System.out.println(emps);}@Testpublic void deleteMoreByArray() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);int result = mapper.deleteMoreByArray(new Integer[]{6, 7, 8, 9});System.out.println(result);}@Testpublic void insertMoreByList() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);Emp emp1 = new Emp(null,"a",1,"男","123@321.com",null);Emp emp2 = new Emp(null,"b",1,"男","123@321.com",null);Emp emp3 = new Emp(null,"c",1,"男","123@321.com",null);List<Emp> emps = Arrays.asList(emp1, emp2, emp3);int result = mapper.insertMoreByList(emps);System.out.println(result);}
}

总结

以上就是MyBatis的详细讲解。

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

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

相关文章

OpenCV4工业缺陷检测的六种方法

机器视觉 机器视觉是使用各种工业相机&#xff0c;结合传感器跟电气信号实现替代传统人工&#xff0c;完成对象识别、计数、测量、缺陷检测、引导定位与抓取等任务。其中工业品的缺陷检测极大的依赖人工完成&#xff0c;特别是传统的3C制造环节&#xff0c;产品缺陷检测依赖于人…

python+torch线性回归模型机器学习

程序示例精选 pythontorch线性回归模型机器学习 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《pythontorch线性回归模型机器学习》编写代码&#xff0c;代码整洁&#xff0c;规则&#xf…

USB2.0 Spec

USB System Description A USB system is described by three definitional areas: • USB interconnect • USB devices • USB host USB interconnect The USB interconnect is the manner in which USB devices are connected to and communicate with the host. USB Ho…

docker基本命令

1.docker命令图解 2. 从仓库拉取镜像 #下载最新版 docker pull nginx # 镜像名:版本名&#xff08;标签&#xff09; docker pull nginx:1.20.1docker rmi 镜像名:版本号/镜像id3. 容器启动及停止 docker run [OPTIONS] IMAGE [COMMAND] [ARG...] docker run [设置项] 镜…

R语言【rgbif】——occ_search对待字符长度大于1500的WKT的特殊处理真的有必要吗?

一句话结论&#xff1a;只要有网有流量&#xff0c;直接用长WKT传递给参数【geometry】、参数【limit】配合参数【start】获取所有记录。 当我在阅读 【rgbif】 给出的用户手册时&#xff0c;注意到 【occ_search】 强调了 参数 【geometry】使用的wkt格式字符串长度。 文中如…

使用数组模拟栈的相关操作【栈1.1】

public class ArrayStackDemo {public static void main(String[] args) {ArrayStack arrayStack new ArrayStack(4);Scanner sc new Scanner(System.in);boolean loop true;char key ;while (loop) {System.out.println("栈操作菜单项");System.out.println(&q…

范仲淹仅存五首词作,篇篇经典

范仲淹&#xff0c;北宋时期杰出的政治家&#xff0c;文学家&#xff0c;提起他首先想到初中那篇《岳阳楼记》&#xff0c;难倒无数背诵困难户&#xff0c;它虽然难背&#xff0c;但却是一篇文字排列极美&#xff0c;意境极佳的美文。 “不以物喜&#xff0c;不以己悲&#xf…

Android hilt使用

一&#xff0c;添加依赖库 添加依赖库app build.gradle.kts implementation("com.google.dagger:hilt-android:2.49")annotationProcessor("com.google.dagger:hilt-android:2.49")annotationProcessor("com.google.dagger:hilt-compiler:2.49"…

程序人生,由“小作文”事件想到的

时势造英雄。自媒体时代&#xff0c;火出圈是靠大众的审美和爱好&#xff0c;自己能做的关键&#xff0c;其实是做好自己&#xff0c;选择向上生长&#xff0c;持续不断的读书、学习。同时保持一份好奇心&#xff0c;培养一个兴趣爱好并自得其乐。 展示自我 回想起我小时候&am…

Promise执行顺序

小编建议小伙伴们不要跳点看&#xff0c;每一点都是衔接&#xff0c;有比较的 本篇文章考查 ①promise是同步任务还是微任务 ②promise.then()什么时候执行&#xff0c;是微任务还是宏任务 ③如何控制状态变化&#xff0c;不同状态变化&#xff0c;会执行哪个回调函数 1、以下代…

进制之间的转换——n进制转换为m进制(C/C++实现,简单易懂)

目录 &#x1f308;前言&#xff1a; &#x1f4c1; 什么是进制转换&#xff1a; &#x1f4c1;其他进制转换成十进制&#xff1a; &#x1f4c2;二进制( B ) ——> 十进制( D ) &#x1f4c2;八进制( O ) ——> 十进制( D ) &#x1f4c2;十六进制( H ) ——> 十进制…

运维实践|采集MySQL数据出现many connection errors

文章目录 问题出现问题分析当前环境问题分析 解决方案1 检查调度事件任务是否开启2 开启调度事件任务3 创建一张日志表4 创建函数存储过程5 创建事件定时器6 开启事件调度任务7 检查核实是否创建 总结 问题出现 最近在做OGG结构化数据采集工作&#xff0c;在数据采集过程中&am…

抖音商品详情API接口在电商行业中的重要性及实时数据获取实现

随着移动互联网的快速发展&#xff0c;电商行业不断壮大。抖音作为一款短视频社交应用&#xff0c;近年来在电商领域取得了显著成果。本文将探讨抖音商品详情API接口在电商行业中的重要性&#xff0c;以及如何通过实时数据获取提高业务效率。我们将介绍相关的技术背景、API接口…

AngularJS

理解实现代码的逻辑为主要&#xff0c;代码怎么写为次要。 参考资料&#xff1a; 《AngularJS入门与进阶》&#xff0c;江荣波著 前端开发常用框架 React&#xff1a;由Facebook开发&#xff0c;用于构建用户界面的JavaScript库&#xff0c;以组件化和虚拟DOM著称。 Angular&…

2024最新FL Studio21.2MAC电脑版中文版下载安装步骤教程

FL Studio 简称FL&#xff0c;全称Fruity Loops Studio&#xff0c;因此国人习惯叫它"水果"。目前最新版本是FL Studio21.1.1.3750版本&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音乐突破…

docker的资源限制及容器应用

一、docker资源限制 在使用 docker 运行容器时&#xff0c;一台主机上可能会运行几百个容器&#xff0c;这些容器虽然互相隔离&#xff0c;但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制&#xff0c;那么容器之间会互相影响&#xff0c;小的来说…

DC-5靶场

目录 DC-5靶机&#xff1a; 先进行主机发现&#xff1a; 发现文件包含&#xff1a; 上传一句话木马&#xff1a; 反弹shell&#xff1a; 提权漏洞利用&#xff1a; 下载exp&#xff1a; 第一个文件 libhax.c 第二个文件r…

电子电器架构( E/E) 演化 —— 大算力

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

PowerShell实战:Get-Content命令使用详解

目录 一、Get-Content介绍 二、语法格式 三、参数详解 四、使用案例 4.1 获取文件内容 4.2 获取文件前三行内容 4.3 获取文件最后三行内容 4.4通过管道方式获取最后两行内容 4.5使用逗号作为分隔符 4.6 Filter方式读取多个文件 4.7 Include方式读取多个文件 一、Get-Content介绍…

Oracle VM VirtualBox使用——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

简述&#xff1a; Oracle VM VirtualBox是一款开源虚拟机软件&#xff0c;由德国Innotek公司开发&#xff0c;后被Sun Microsystems公司收购&#xff0c;并最终被甲骨文公司收购。它支持在Windows、Mac OS X、Linux、OpenBSD、Solaris、IBM OS2甚至Android等操作系统上创建虚拟…