【Mybatis】日常知识点随笔(持续更新)

news2024/7/6 19:17:50

目录

【K】Mybatis使用@Select注解书写简单sql

【K】MySQL 数据类型与 Java 类型的对应关系

【K】Mybatis相同代码复用

1. 定义公共 SQL 片段

2. 引用公共 SQL 片段

3. 使用参数

4. 复用和组合

5. 注意事项

【K】mysql如何实现插入一条数据后立刻获取该数据自增长id进行调用

背景解析

代码使用

【K】Mybatis新增数据,存在就更新,不存在就添加

常规方法

Replace关键字

【K】MyBatis执行多个sql语句

背景

代码举例

实例举例

分析总结

【K】Mybatis 不同条件拼接不同sql

举例1

举例2: 判断某一个值

举例3

【K】-IFNULL处理N/A

背景知识

SQL语句分析

改进后的SQL语句

知识扩展

注意事项

【K】Mybatis条件查询<where>标签

【K】使用resultMap封装对象一对多

数据库模型

实体类

MyBatis 配置

举例

【K】Mybatis使用常见类型的类型别名


【K】Mybatis使用@Select注解书写简单sql

//1. 基本查询
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUserById(int id);

//2. 动态查询
@Select("<script>" +
        "SELECT * FROM users" +
        "<if test='id != null'>" +
        " WHERE id = #{id}" +
        "</if>" +
        "</script>")
List<User> selectUsersById(@Param("id") Integer id);

//3. 返回 Map
@Select("SELECT * FROM users")
@MapKey("id")
Map<Integer, User> selectUsersAsMap();

//4. 使用注解参数
@Select("SELECT * FROM ${tableName}")
List<User> selectUsersFromTable(@Param("tableName") String tableName);

//5. 结果映射
@Select("SELECT id, name, email FROM users WHERE id = #{id}")
@Results({
    @Result(property = "id", column = "id"),
    @Result(property = "name", column = "name"),
    @Result(property = "email", column = "email")
})
User selectUserDetailedById(int id);

//6. 联合查询
@Select("SELECT u.id, u.name, a.city FROM users u INNER JOIN address a ON u.id = a.user_id WHERE u.id = #{id}")
User selectUserWithAddress(int id);

//7. 分页查询
@Select("SELECT * FROM users LIMIT #{limit} OFFSET #{offset}")
List<User> selectUsersByPage(@Param("limit") int limit, @Param("offset") int offset);

【K】MySQL 数据类型与 Java 类型的对应关系

在 MyBatis 中,Java 类型和 MySQL 数据库类型之间的映射是通过 `typeHandlers` 来实现的。以下是一些常见的 MySQL 数据类型与 Java 类型的对应关系,以及在 MyBatis 的 XML 配置文件中如何配置它们的示例。

MySQL 数据类型Java 类型MyBatis XML 配置中的类型别名
CHARStringVARCHAR
VARCHARStringVARCHAR
BLOBbyte[]BLOB
TEXTStringVARCHAR
INTEGERint/IntegerINTEGER
TINYINTbyte/ByteTINYINT
SMALLINTshort/ShortSMALLINT
MEDIUMINTint/IntegerINTEGER
BIGINTlong/LongBIGINT
FLOATfloat/FloatFLOAT
DOUBLEdouble/DoubleDOUBLE
DECIMALjava.math.BigDecimalDECIMAL
DATEjava.sql.DateDATE
TIMEjava.sql.TimeTIME
DATETIMEjava.sql.TimestampTIMESTAMP
TIMESTAMPjava.sql.TimestampTIMESTAMP
BOOLEANboolean/BooleanBOOLEAN
ENUMStringVARCHAR
SETStringVARCHAR

在 MyBatis 的配置文件 `mybatis-config.xml` 中,你不需要为每种类型映射都显式定义 `typeHandler`,因为 MyBatis 已经内置了对这些常见类型的处理。但如果你需要自定义类型处理器,你可以这样配置:

<typeHandlers>
  <typeHandler handler="com.example.MyCustomTypeHandler"/>
</typeHandlers>

以下是一个包含所有类型映射的 MyBatis 映射文件 (`UserMapper.xml`) 示例:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">

  <resultMap id="UserResultMap" type="User">
    <result property="id" column="id" javaType="int" jdbcType="INTEGER" />
    <result property="username" column="username" javaType="String" jdbcType="VARCHAR" />
    <result property="password" column="password" javaType="String" jdbcType="VARCHAR" />
    <result property="email" column="email" javaType="String" jdbcType="VARCHAR" />
    <result property="profilePhoto" column="profile_photo" javaType="byte[]" jdbcType="BLOB" />
    <result property="age" column="age" javaType="Integer" jdbcType="TINYINT" />
    <result property="balance" column="balance" javaType="java.math.BigDecimal" jdbcType="DECIMAL" />
    <result property="birthDate" column="birth_date" javaType="java.sql.Date" jdbcType="DATE" />
    <result property="loginTime" column="login_time" javaType="java.sql.Timestamp" jdbcType="TIMESTAMP" />
    <result property="isActive" column="is_active" javaType="Boolean" jdbcType="BOOLEAN" />
  </resultMap>

  <select id="selectUsers" resultMap="UserResultMap">
    SELECT * FROM users
  </select>

  <!-- Other CRUD operations go here -->

</mapper>

在这个示例中,`<resultMap>` 定义了如何将数据库表 `users` 中的列映射到 Java 类 `User` 的属性上。每个 `<result>` 元素指定了一个属性到列的映射,包括 Java 类型 (`javaType`) 和 JDBC 类型 (`jdbcType`)。

请注意,实际开发中可能不需要为每个字段都显式指定 `jdbcType`,因为 MyBatis 通常能够推断出对应的类型。但在某些情况下,特别是当 MyBatis 无法准确推断类型时(例如对于 `null` 值),指定 `jdbcType` 可以避免类型相关的错误。

【K】Mybatis相同代码复用

在 MyBatis 中,为了避免重复编写相同的 SQL 片段,可以使用 `<sql>` 元素定义可重用的 SQL 代码块,并通过 `<include>` 元素在需要的地方引入这些代码块。这种方式提高了代码的可维护性和可读性。以下是如何使用这些元素来提取和复用相同的代码段的总结:

1. 定义公共 SQL 片段

   使用 `<sql>` 标签定义公共的 SQL 片段,并为其指定一个唯一的 `id`。这个 `id` 将在后续的 `<include>` 标签中被引用。

   <sql id="common_sql_where">
       <if test="id != null">
           AND id = #{id}
       </if>
       <!-- 可以继续添加其他公共条件 -->
   </sql>

2. 引用公共 SQL 片段

   在实际的查询语句中,使用 `<include>` 标签引入公共 SQL 片段。通过 `refid` 属性指定需要引入的公共 SQL 片段的 `id`。

   <select id="selectWithCommonWhere" resultType="YourResultType">
       SELECT * FROM your_table WHERE 1=1
       <include refid="common_sql_where"/>
   </select>

3. 使用参数

   在公共 SQL 片段中,可以使用 MyBatis 的参数占位符 `#{}` 来引用传入的参数。确保传入的参数名称与 `<if>` 测试条件中的参数名称相匹配。

4. 复用和组合

   可以将多个 `<sql>` 片段组合在一起,使用多个 `<include>` 标签来构建复杂的查询条件。

   <select id="selectAdvanced" resultType="YourResultType">
       SELECT * FROM your_table
       WHERE 1=1
       <include refid="common_sql_where"/>
       <!-- 可以继续引入其他公共 SQL 片段 -->
   </select>

5. 注意事项

   - 确保 `<include>` 标签中的 `refid` 正确无误地指向了预定义的 `<sql>` 片段的 `id`。
   - 在 `<sql>` 片段中定义的条件必须符合 SQL 语法,特别是在使用 `<if>` 条件时要注意不要遗漏必要的 SQL 关键字,比如 `AND`。
   - 当在 `<sql>` 片段中使用动态 SQL(如 `<if>`)时,要注意条件的逻辑组合,以避免生成无效的 SQL。

通过这种方式,可以有效地管理和复用 SQL 代码,减少冗余,并使得 SQL 语句的维护变得更加简单。

【K】mysql如何实现插入一条数据后立刻获取该数据自增长id进行调用

背景解析

useGeneratedKeys 取值范围true|false 默认值是:false。
含义:设置是否使用JDBC的.

getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。

代码使用

  <insert id="insert" parameterType="com.hy.common.entity.User"
          useGeneratedKeys="true" keyProperty="id">
    insert into user (name, age)
    values ( #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER})
  </insert>
    @Override
    @Transactional(readOnly = false)
    public int insertUser() {
        User user = new User();
        user.setName("why");
        user.setAge(18);
 
        int count = userMapper.insert(user);
        System.out.println(count);   // 插入的条数:1
        int id = user.getId();   
        System.out.println(id); // 自增的id:666
 
        return id;
    }

【K】Mybatis新增数据,存在就更新,不存在就添加

常规方法

先查询是否存在,存在就更新,不存在就添加.

如果数据量过大, 使用foreach批量操作

举例: 集合唯一索引  id

可以查询所有的id集合idSet,  使用in idSet查询那些存在, 返回结果集oldSet.

然后遍历判断idSet是否存在oldSet, 存在走更新逻辑,不存在走添加逻辑.

Replace关键字

REPLACE关键字的使用

      使用REPLACE的最大好处就是可以将DELETE和INSERT合二为一,形成一个原子操作。这样就可以不必考虑在同时使用DELETE和INSERT时添加事务等复杂操作了。
      在使用REPLACE时,表中必须有唯一索引,而且这个索引所在的字段不能允许空值,否则REPLACE就和INSERT完全一样的。
      在执行REPLACE后,系统返回了所影响的行数,如果返回1,说明没有重复的记录,如果返回2,说明有重复记录,系统先DELETE这条记录,然后再INSERT这条记录。
语法和INSERT非常的相似,如下面的REPLACE语句是插入或更新一条记录。

REPLACE INTO users (id,name,age) VALUES(1, '李嘉欣', 18); 

【K】MyBatis执行多个sql语句

背景

驱动默认不开启支持多个sql执行。
在数据库连接的url增加参数allowMultiQueries,值为true,多个SQL直接一以“;”分隔即可

xxx.jdbcUrl=jdbc:mysql://xx.xx.xx:3306/xxxxx?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true

&allowMultiQueries=true

代码举例

<select id="getUserAndOrders" resultSets="user,orders">
  select * from user where id = #{id};
  select * from orders where user_id = #{id};
</select>

实例举例

场景:

删除用户的时候需要先删除用户的外键关联数据,否则会触发规则报错。

本人遇到的是循环拼接不同字段条件的修改sql执行。

直接写多条语句,用“;”隔开即可

<delete id="deleteUserById" parameterType="String">
    delete from sec_user_role where userId=#{id};
    delete from sec_user where id=#{id};
</delete>

分析总结

执行多个SQL查询并返回多个结果集的原因简述:

  • 在某些业务场景中,需要从不同的数据表中提取数据并组合成一个复合数据对象。
  • 执行多个查询并一次性返回所有结果集可以减少数据库IO操作,提高性能。
  • 将相关查询逻辑集中到一个地方有助于提高代码的可读性和可维护性。

MyBatis执行多个查询并处理结果集的方法简述:

  • MyBatis允许通过resultSets属性在一个<select>元素中执行多个查询并命名各个结果集。
  • 可以使用SqlSession的selectList或selectMap方法来获取这些结果集。
  • 结果集可以映射到不同的Java对象,并可通过自定义resultMap进行详细配置。

总结:

MyBatis支持一次执行多个SQL查询并返回多个结果集,这有助于优化性能和提升代码质量。

【K】Mybatis 不同条件拼接不同sql

在MyBatis中,可以使用动态SQL功能来根据不同的条件拼接不同的SQL语句。动态SQL是MyBatis的一大特色,它允许在XML映射文件中构建灵活的SQL语句。主要通过<if>, <choose>, <when>, <otherwise>, <where>, <set>, <foreach>等元素来实现条件逻辑。

举例1

以下是一个使用MyBatis动态SQL的例子,我们将创建一个根据不同条件来查询用户的例子。

首先,定义一个User对象和一个UserMapper接口:

// User.java
public class User {
    private Integer id;
    private String name;
    private String email;
    // getters and setters...
}

// UserMapper.java
public interface UserMapper {
    List<User> findUsers(Map<String, Object> params);
}

然后,在MyBatis的XML映射文件中,我们定义动态SQL查询:

<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
    <select id="findUsers" resultType="com.example.User">
        SELECT id, name, email
        FROM users
        <where>
            <if test="id != null">
                AND id = #{id}
            </if>
            <if test="name != null">
                AND name = #{name}
            </if>
            <if test="email != null">
                AND email = #{email}
            </if>
        </where>
    </select>
</mapper>

在这个例子中,<where>元素会智能地插入WHERE关键字,并且只有当内部的条件成立时才会插入相应的条件语句,并且会处理好条件语句前的AND或OR关键字。

现在,当我们调用findUsers方法时,可以传递一个包含id、name、email等键的Map对象。MyBatis会根据Map中的键值对是否存在来动态构建SQL语句。

// 使用MyBatis的SqlSession来执行查询
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    Map<String, Object> params = new HashMap<>();
    params.put("name", "John Doe");
    List<User> users = mapper.findUsers(params);
    // 处理查询结果...
} finally {
    sqlSession.close();
}

在上面的Java代码中,我们创建了一个包含"name"键的Map,并将其作为参数传递给findUsers方法。MyBatis会生成一个包含AND name = 'John Doe'条件的SQL语句,因为Map中只有"name"键。

举例2: 判断某一个值

不同条件拼接不同sql

</where>
    ORDER BY
<if test="name != null and name !='' and name == '1'.toString()">
    dept DESC
</if>
<if test="name != null and name !='' and name == '2'.toString()">
    type DESC
</if>

Postman访问

注意事项

前言:
name代码为String,
XML 代码为: <if test="name != null and name !='' and name == '1'.toString()">
  1. postman入参可以为"name": "1",或"name": 1
  2. '1'需要加上单引号
  3. 加单引号后为字符,类型为Charactor

举例3

某些特殊业务场景下的, 为了替换#{demoWay}的替换写法...

            <if test="demoWay != null  and test="demoWay != '' ">
                <if test="demoWay == 'equal' ">
                    <![CDATA[ and demo_str = #{demoStr} ]]> </if>
                <if test="demoWay == 'gt' ">
                    <![CDATA[ and demo_str > #{demoStr} ]]> </if>
                <if test="demoWay == 'lt' ">
                    <![CDATA[ and demo_str < #{demoStr} ]]> </if>
                <if test="demoWay == 'gte' ">
                    <![CDATA[ and demo_str >= #{demoStr} ]]> </if>
                <if test="demoWay == 'lte' ">
                    <![CDATA[ and demo_str <= #{demoStr} ]]> </if>
            </if>

这种动态SQL的方法使得SQL语句的构建非常灵活,可以根据传入的参数不同构建不同的查询条件,而不必编写多个几乎相同的查询语句。这样的设计既简化了代码,也使得维护更加容易。

【K】-IFNULL处理N/A

背景知识

在数据库中,有时需要生成具有特定格式的唯一ID。例如,这里的ID由当前日期(格式为yyyymmdd)和一个顺序号(四位数)组成。每当需要添加新的记录时,就要生成一个新的ID,该ID比当天已有的最大ID大1。

SQL语句分析

原始的SQL语句试图获取当天最大的ID,然后将其加1以生成新的ID。如果当天没有ID,就默认使用'0001'作为顺序号。

公司表获取最大ID且加1:
ID示例:yyyymmdd+0001

SELECT
    IFNULL(RIGHT(ac.id + 1, 4), '0001') numMax
FROM
    app_company ac
WHERE
    LEFT(ac.id, 8) = DATE_FORMAT(now(), '%Y%m%d')
ORDER BY
    RIGHT(ac.id, 4) DESC
LIMIT 1

这个查询有几个问题:

  • IFNULL函数不会处理非NULL的“无效”值(如'N/A')。
  • 在没有任何记录的情况下,RIGHT(ac.id + 1, 4)将不会返回任何结果,因此IFNULL将返回'0001'。
  • 使用ORDER BY和LIMIT来获取最大值效率较低。

改进后的SQL语句

改进后的SQL语句使用MAX函数来找出当天最大的ID,然后通过IFNULL处理当天没有任何ID的情况。这样就不需要ORDER BY和LIMIT子句,因为MAX函数已经能够找到最大的ID。

SELECT
    IFNULL(MAX(RIGHT(ac.id, 4)) + 1, '0001') numMax
FROM
    app_company ac
WHERE
    LEFT(ac.id, 8) = DATE_FORMAT(now(), '%Y%m%d')

知识扩展

  • IFNULL: MySQL中的IFNULL函数用来检查第一个表达式是否为NULL,如果是,就返回第二个参数的值。
  • MAX: MAX函数返回一组值中的最大值,如果集合为空,则返回NULL。
  • RIGHT: RIGHT函数从字符串的右侧返回指定数量的字符。
  • LEFT: LEFT函数从字符串的左侧返回指定数量的字符。
  • DATE_FORMAT: DATE_FORMAT函数用于格式化日期值。

注意事项

在实际使用中,直接在数据库层面进行ID的生成可能会有并发问题,特别是在高并发的环境下。为了确保ID的唯一性和顺序,可能需要采用其他机制,比如应用层的锁或者使用数据库的序列(在MySQL 8.0+中为AUTO_INCREMENT属性)。

此外,如果ac.id是字符型字段,直接进行+ 1操作可能会导致错误,因为字符型和数值型的操作不同。在这种情况下,可能需要先将ID的顺序号部分转换为数值型,进行加法操作后再转换回字符型。

【K】Mybatis条件查询<where>标签

MyBatis 的 <where> 标签用于动态生成 SQL 查询语句中的 WHERE 条件。该标签的主要作用是简化 SQL 编写,并自动处理 WHERE 关键字和条件之间的逻辑关系(如 AND 或 OR)。当内部条件为空时,它会智能地省略 WHERE 关键字,而当有条件时,则会自动加上 WHERE 关键字。这样可以避免在动态 SQL 中手动编写复杂的逻辑来判断是否需要添加 WHERE 关键字。
<where> 标签的基本规则:

    <where> 标签内部可以包含 <if>、<choose>、<when>、<otherwise> 等子标签。
    如果 <where> 标签内部的条件都不成立,则整个 <where> 标签不会生成任何内容。
    如果 <where> 标签内部至少有一个条件成立,则会自动在这些条件前添加 WHERE 关键字。
    <where> 标签会自动处理条件之间的第一个 AND 或 OR 关键字。

示例:

假设我们有一个 User 表,包含 id、name、email 等字段,现在我们要根据这些字段的不同组合来查询用户。

UserMapper 接口:

public interface UserMapper {
    List<User> findUsers(Map<String, Object> params);
}

UserMapper.xml 映射文件:

<mapper namespace="com.example.mapper.UserMapper">
    <select id="findUsers" resultType="com.example.User">
        SELECT id, name, email
        FROM User
        <where>
            <if test="id != null">
                id = #{id}
            </if>
            <if test="name != null and name != ''">
                AND name = #{name}
            </if>
            <if test="email != null and email != ''">
                AND email = #{email}
            </if>
        </where>
    </select>
</mapper>

在上述例子中:

  • 如果 params 中没有任何一个键值对,则 SQL 语句将是 SELECT id, name, email FROM User。
    如果 params 中只有 name 键值对,则 SQL 语句将是 SELECT id, name, email FROM User WHERE name = '指定的name值'。
    如果 params 中有 name 和 email 键值对,则 SQL 语句将是 SELECT id, name, email FROM User WHERE name = '指定的name值' AND email = '指定的email值'。

这种方式确保了 WHERE 条件的灵活性和正确性,同时避免了手动编写复杂的逻辑来控制 SQL 语句的准确性。使用 <where> 标签可以大大提高 SQL 语句的可维护性和可读性。

【K】使用resultMap封装对象一对多

在 MyBatis 中,`resultMap` 是一个非常强大的映射工具,它能够处理复杂的数据库关系,如一对一、一对多和多对多的关系。通过正确使用 `resultMap`,可以在执行单个查询时获取关联的数据,而不必执行多次查询,这样可以提高应用程序的性能。

下面是一个使用 `resultMap` 来处理一对一和一对多关系的完整示例。

数据库模型

假设我们有以下三个表:

1. 用户表 `user`
2. 部门表 `department`
3. 用户联系人表 `user_linkman`

用户表(user):

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int(2) unsigned DEFAULT NULL,
  `department_id` int(11) NOT NULL COMMENT '部门id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

部门表(department):

CREATE TABLE `department` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门id',
  `department_name` varchar(255) DEFAULT NULL COMMENT '部门名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='部门表';

用户联系人表(user_linkman):

CREATE TABLE `user_linkman` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户联系人表主键id',
  `user_id` int(11) DEFAULT NULL COMMENT '用户id',
  `linkman_id` varchar(255) DEFAULT NULL COMMENT '联系人id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='用户联系人表';

实体类

用户实体类(User):

package com.example.demo.entity;

import lombok.Data;
import java.util.List;

@Data
public class User {
    private String id;
    private String code;
    private String name;
    private int age;
    private Department department;      // 对应部门实体
    private List<UserLinkman> linkmenList; // 对应联系人列表
}

MyBatis 配置

在 MyBatis 的映射文件中,我们可以定义一个 `resultMap` 来描述如何从数据库结果集映射到我们的实体类。

<resultMap id="userResultMap" type="User">
    <id property="id" column="id" />
    <result property="code" column="code" />
    <result property="name" column="name" />
    <result property="age" column="age" />
    <association property="department" column="department_id" javaType="Department" select="selectDepartmentById" />
    <collection property="linkmenList" ofType="UserLinkman" column="id" select="selectLinkmanListByUserId" />
</resultMap>

<select id="selectDepartmentById" resultType="Department">
    SELECT id, department_name AS 'departmentName' FROM department WHERE id = #{id}
</select>

<select id="selectLinkmanListByUserId" resultType="UserLinkman">
    SELECT id, user_id AS 'userId', linkman_id AS 'linkmanId' FROM user_linkman WHERE user_id = #{id}
</select>

<select id="selectUserById" resultMap="userResultMap">
    SELECT * FROM user WHERE id = #{id}
</select>

在上述配置中,我们定义了一个 `userResultMap`:

- `<association>` 用于处理一对一的关系,这里是用户和部门的关系。
- `<collection>` 用于处理一对多的关系,这里是用户和联系人的关系。

通过这种配置,当我们调用 `selectUserById` 查询时,MyBatis 会自动执行 `selectDepartmentById` 和 `selectLinkmanListByUserId` 查询来填充 `User` 实体中的 `department` 和 `linkmenList` 属性。

举例

假设我们需要查询某次考试的所有单位信息,包括名称、参考人数、通过人数、通过率,以及本部门所有参考人员的信息。我们可以创建一个对应的 `resultMap`:

<resultMap id="CountResultMap" type="com.example.demo.entity.vo.ExamTestVo">
    <result column="department" jdbcType="VARCHAR" property="department"/>
    <result column="exam_num" jdbcType="VARCHAR" property="examNum"/>
    <result column="pass_num" jdbcType="VARCHAR" property="passNum"/>
    <result column="percent_pass" jdbcType="VARCHAR" property="percentPass"/>
    <collection property="userList" javaType="list" column="id" ofType="User" select="selectUserListByExamId" />
</resultMap>

这里的 `<collection>` 标签将会把某个考试 ID 对应的所有用户信息作为一个列表映射到 `ExamTestVo` 的 `userList` 属性中。这样,通过单个查询,我们就能获取一个考试的所有相关信息,包括每个单位的详细数据和参考人员的列表。

【K】Mybatis使用常见类型的类型别名

MyBatis 提供了一系列内置的类型别名,用于简化 XML 配置文件中的类型引用。这些别名代表了 Java 中的一些常见类型。使用类型别名可以让你的 MyBatis 配置文件更加简洁易懂。

下面是一些常见的 MyBatis 内置类型别名及其对应的 Java 类型:

Java 类型MyBatis 别名
byte_byte
long_long
short_short
int_int
Integer_integer
double_double
float_float
boolean_boolean

还有一些引用类型的别名:

Java 类型MyBatis 别名
Stringstring
Bytebyte
Longlong
Shortshort
Integerint
Doubledouble
Floatfloat
Booleanboolean
Datedate
BigDecimaldecimal
BigDecimalbigdecimal
Objectobject
Mapmap
HashMaphashmap
Listlist
ArrayListarraylist
Collectioncollection
Iteratoriterator

使用这些类型别名的例子:

<select id="selectUserById" resultType="_int">
    SELECT age FROM user WHERE id = #{id}
</select>

<select id="selectUserName" resultType="string">
    SELECT name FROM user WHERE id = #{id}
</select>

<select id="selectAllUsers" resultType="map">
    SELECT * FROM user
</select>

在上述例子中,`resultType="_int"` 表示查询的结果是一个基本类型 `int`,`resultType="string"` 表示查询的结果是 `String` 类型,而 `resultType="map"` 表示查询的结果是 `Map` 类型的集合。

要注意的是,当我们使用类型别名 `_int` 时,通常是在查询返回单个值的场景,比如统计数量或者查询某个特定的数值

有用请点赞,养成良好习惯!

疑问、交流、鼓励请留言!

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

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

相关文章

软件测试面试:测试基础题

软件测试的流程是什么&#xff1f;&#xff08;测试流程&#xff09; &#xff08;1&#xff09;需求调查&#xff1a;全面了解系统概况、应用领域、软件开发周期、软件开发环境、开发组织、时间安排、功能需求、性能需求、质量需求及测试要求等。根据系统概况进行项目所需的人…

flowable-startEvent[开始事件]相关配置[表单、执行监听器]

flowable各个事件、网关、任务的使用详解 既然网上没有合适的教程&#xff0c;那就力求达到先会用&#xff0c;再理解。 当然各个事件有一些功能是重复的&#xff0c;比如事件和任务都有执行监听器&#xff0c;这个等说到任务的时候就会提一下&#xff0c;然后带过。 今天只看“…

FFmpeg 简单文档

一、播放器框架 常用音视频术语 容器&#xff0f;文件&#xff08;Conainer/File&#xff09;&#xff1a;即特定格式的多媒体文件&#xff0c;比如mp4、flv、mkv等。媒体流&#xff08;Stream&#xff09;&#xff1a;表示时间轴上的一段连续数据&#xff0c;如一段声音数据、…

MySQL调优参考文档-MSB

1.操作与落地 1.1.数据库基础知识 1.1.1.范式化设计 1.1.1.1.什么是范式 范式来自英文Normal Form&#xff0c;简称NF。 实际上你可以把它粗略地理解为 一张数据表的表结构所符合的某种设计标准的级别 。就像家里装修买建材&#xff0c;最环保的是E0级&#xff0c;其次是E…

详细教程 - 进阶版 鸿蒙harmonyOS应用 第十二节——鸿蒙操作系统中的动画效果封装:Java和TypeScript版

简介 动画效果是开发鸿蒙应用时的一个重要功能。在这篇文章中&#xff0c;我们将详细探讨如何在鸿蒙系统中使用Java和TypeScript实现动画效果的封装&#xff0c;并提供一些代码示例。 Java版动画效果的实现 在鸿蒙操作系统中&#xff0c;我们可以使用ohos.agp.animation.Anima…

Python往事:ElementTree的单引号之谜

最近在针对某款设备的界面xml进行更新过程中&#xff0c;被告知回稿的字串放在了一个excel文件中&#xff0c;而我要上传到服务器的界面用语是用xml文件封装的。再经过详细求证了翻译组提供excel文件的原因后&#xff0c;我决定用python来完成界面用语xml的更新&#xff0c;但是…

5年开酸奶店的经历,告诉小白如何做市场调查

在开酸奶店之前&#xff0c;市场调查是必不可少的一步。 作为一个有 5 年开店经验的酸奶店老板&#xff0c;我将分享一些关于如何进行市场调查的实用建议。 1、确定目标市场 在开始市场调查之前&#xff0c;你需要先明确你的目标市场。你的酸奶店将面向哪些人群&#xff1f;…

如何通过ssh管道传输文件到ubuntu

如何在window系统中&#xff0c;通过ssh将指定的文件传输到ubuntu中呢&#xff1f; 比较常用的有以下种方式&#xff1a; 共享文件夹借助工具&#xff0c; FileZillaMobaxtermWinSCPXshell XFTP samba互传PuTTY pscp 今天主要分享一个使用python脚本搭建的一个&#xff0c;…

2023.12.17 关于 Redis 的特性和应用场景

目录 引言 Redis 特性 内存中存储数据 可编程性 可扩展性 持久化 支持集群 高可用性 Redis 优势 Redis 用作数据库 Redis 相较于 MySQL 优势 Redis 相较于 MySQL 劣势 Redis 用作缓存 典型场景 Redis 存储 session 信息 Redis 用作消息队列 初心 消息队列的…

谷歌手机安装证书到根目录

1、前提你已经root&#xff0c;安装好面具 2&#xff0c;下载movecert模块&#xff0c;自动帮你把证书从用户证书移动成系统证书 视频教程&#xff0c;手机为谷歌手机 https://www.bilibili.com/video/BV1pG4y1A7Cj?p11&vd_source9c0a32b00d6d59fecae05b4133f22f06 软件下…

众和策略:短线交易看什么?短线交易看什么指标?

短线交易看什么&#xff1f; 1、k线 当k线出现黄昏十字星、黑乌鸦、乌云盖顶等卖出形状图时&#xff0c;是一种卖出信号&#xff0c;当k线出现早晨十字星、红三兵、等买入形状图时&#xff0c;是一种买入信号。 2、均线 当均线出现死叉、空头摆放时是一种卖出信号&#xff…

商城免 费搭建之java鸿鹄云商 java电子商务商城 Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

【saas云平台】打造全行业全渠道全场景的saas产品&#xff0c;为经营场景提供一体化解决方案&#xff1b;门店经营区域化、网店经营一体化&#xff0c;本地化、全方位、一站式服务&#xff0c;为多门店提供统一运营解决方案&#xff1b;提供丰富多样的营销玩法覆盖所有经营场景…

SpringIOC之ScopeMetadata

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

《服务器之间的图片传输 2023-12-19》模拟一台服务器(client)给另外一台服务(server)传输图片

Server public class PictureTestServer {public static void main(String[] args) {try (ServerSocket serverSocket new ServerSocket(0)) {System.out.println("服务器已启动&#xff0c;监听端口: " serverSocket.getLocalPort());Socket socket serverSocke…

Three.js中文网14入门案例

Three.js中文网 <template><div id"webgl"></div> </template><script setup> import * as THREE from three; import { OrbitControls } from three/addons/controls/OrbitControls.js;// 创建3D场景对象Scene const scene new TH…

ansible远程操作主机功能(1)

自动化运维&#xff08;playbook剧本yaml&#xff09; 是基于Python开发的配置管理和应用部署工具。自动化运维中&#xff0c;现在是异军突起。 Ansible能批量配置&#xff0c;部署&#xff0c;管理上千台主机&#xff0c;类似于Xshell的一键输入的工具&#xff0c;不需要每次…

playwright进阶问题,with sync_playwright() as p中的p是什么类型您知道吗?

playwritght中with as的用法 最近在看playwritght 的源码&#xff0c;大家都知道运行playwright的基础代码如下&#xff1a; with sync_playwright() as p:browser p.chromium.launch(channel"chrome", headlessFalse)page browser.new_page()page.goto("ht…

国产ToolLLM的课代表---OpenBMB机构(清华NLP)旗下ToolBench的安装部署与运行(附各种填坑说明)

ToolBench项目可以理解为一个能直接提供训练ToolLLM的平台&#xff0c;该平台同时构建了ToolLLM的一个开源训练指令集。&#xff0c;该项目是OpenBMB机构&#xff08;面壁智能与清华NLP联合成立&#xff09;旗下的一款产品&#xff0c;OpenBMB机构名下还同时拥有另外一款明星产…

JAVA编程题-交通工具信息查询系统

题目&#xff1a; 请编写一个交通工具信息查询系统&#xff0c;其中包含一个抽象父类&#xff1a;交通工具&#xff08;Transports&#xff09;类&#xff0c;四个具体子类飞机&#xff08;Plane&#xff09;类&#xff0c;轮船&#xff08;Ship&#xff09;类&#xff0c;火车…

结构体基础例题

这里写目录标题 例题一例题解析答案 例题二例题解析答案 例题三例题解析答案 例题四例题解析答案 例题五例题解析及答案 例题六例题解析及答案 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &#x1f978…