【Mybatis -日常使用记录】

文章介绍了Mybatis中使用@Select注解进行SQL查询的各种场景,包括基础查询、动态查询、返回Map、参数化查询、结果映射、联合查询和分页查询。同时详细讲解了MySQL数据类型与Java类型的对应关系以及如何通过typeHandlers进行映射配置。
摘要由CSDN通过智能技术生成

1、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);

2、MySQL 数据类型与 Java 类型的对应关系

在 MyBatis 中,Java 类型和 MySQL 数据库类型之间的映射是通过 typeHandlers 来实现的。以下是一些常见的 MySQL 数据类型与 Java 类型的对应关系,以及在 MyBatis 的 XML 配置文件中如何配置它们的示例。
在这里插入图片描述
在这里插入图片描述
在 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 可以避免类型相关的错误。

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 语句的维护变得更加简单。

Mybatis条件查询<where>标签

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

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

使用resultMap封装对象一对多

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

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

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 会自动执行 selectDepartmentByIdselectLinkmanListByUserId 查询来填充 User 实体中的 departmentlinkmenList 属性。

举例

假设我们需要查询某次考试的所有单位信息,包括名称、参考人数、通过人数、通过率,以及本部门所有参考人员的信息。我们可以创建一个对应的 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 对应的所有用户信息作为一个列表映射到 ExamTestVouserList 属性中。这样,通过单个查询,我们就能获取一个考试的所有相关信息,包括每个单位的详细数据和参考人员的列表。

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

版权声明:本文为CSDN博主「慕白Lee」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/libusi001/article/details/135070117

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

無飞

叠码不易,鼓励鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值