【转载】关于Mybatis的@Param注解

本文详细解析了Mybatis框架中参数传递的四种常见场景,包括单个参数与多个参数的传递方式,探讨了@Param注解的使用及其对代码的影响,为开发者提供了实用的编码指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://blog.youkuaiyun.com/mrqiang9001/article/details/79520436

Mybatis 作为一个轻量级的数据持久化框架,目前(2018)的应用非常广泛,基本可以取代Hibernate。关于 @param 这个注解的使用,作者这里整理了一些笔记。

关于Mybatis @Param 注解,官方文档: http://www.mybatis.org/mybatis-3/zh/java-api.html
其中关于 @param部分的说明是:

@Param    Parameter    N/A    如果你的映射器的方法需要多个参数, 这个注解可以被应用于映射器的方法 参数来给每个参数一个名字。否则,多 参数将会以它们的顺序位置来被命名 (不包括任何 RowBounds 参数) 比如。 #{param1} , #{param2} 等 , 这 是 默 认 的 。 使 用 @Param(“person”),参数应该被命名为 #{person}。
也就是说如果有多个参数的时候,可以使用@Param 这个注解,但是不是一定需要用到 @Param 这个注解呢?作者在这里列出以下几种情景

1.传递单个参数,不使用 @Param 注解

代码如下:
DAO 层 CommodityDao.java

package com.ljq.cs.dao;
/**
 * @description: 商品信息 DAO 接口
 * @author: lujunqiang
 * @email: flying9001@gmail.com
 * @date: 2017/12/17
 */
@Repository
public interface CommodityDao {

    //    查询某一件商品
    Commodity queryOne(Commodity commodity);
    
    // 省略其他方法 
        
}


Mapper 文件: commoditymapper.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.ljq.cs.dao.CommodityDao" >
    
    <select id="queryOne" resultType="Commodity">
        select *
        from t_commodity com 
        where id = #{id}
    </select>        
</mapper>



这里只有一个参数,java 接口不使用 @Param 注解,同时 mapper 文件也不需要使用 parameterType 这个参数,Mybatis会 根据实体类(entity)的类型自动识别并匹配javaBean(这一部分在 spring配置文件关于数据源那一部分)

2.传递单个参数,使用@Param注解

代码如下:
DAO 层 CommodityDao.java

package com.ljq.cs.dao;

/**
 * @description: 商品信息 DAO 接口
 * @author: lujunqiang
 * @email: flying9001@gmail.com
 * @date: 2017/12/17
 */
@Repository
public interface CommodityDao {

    //    查询某一件商品
    Commodity queryOne(@Param("commodity")Commodity commodity);
    
    // 省略其他方法 
        
}



Mapper 文件: commoditymapper.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.ljq.cs.dao.CommodityDao" >
    
    <select id="queryOne" parameterType="com.ljq.cs.entity.Commodity" resultType="Commodity">
        select *
        from t_commodity com 
        where id = #{commodity.id}
    </select>        
</mapper>

当使用javaBean作为对象的时候,在写 SQL 语句的时候,必须指定参数类型 parameterType="com.ljq.cs.entity.Commodity",同时在 #{ } 取值的时候不能直接填入 javaBean 的属性,必须这样使用 commodity.id ;否则,会抛出参数类型不匹配异常
如果不是 javaBean,则需要在写 SQL 语句的时候, #{ } 中的属性必须与 @Param中定义的一致,eg: @Param("username") , #{username} ,这样才可以

3.传递多个参数,使用 @Param 注解

为了精简代码,作者这里只写关键部分
DAO 层, UserInfoDao.java

//    用户登录
    UserInfo signin(@Param("account")String account,@Param("passcode")String passcode);
    

mapper文件userInfomapper.xml

 <!-- 用户登录 -->
    <select id="signin" resultType="UserInfo">
        select *
        from t_userinfo info
        where account=#{account} and passcode=#{passcode}
    </select>


这里 @Param 中定义的变量名必须和 mapper 中保持一致才可以

4.传递多个参数,不使用 @Param 注解

其实从第一种场景中已经可以实现传递多个参数了,即把多个参数封装到一个 javaBean 中就可以实现了,但是如果是两个或者多个 javaBean 的时候,可以通过使用@Param注解的方式来实现,但是需要把每个 javaBean 中的属性全部拆分出来,这样就增加了巨大的代码量,因此不推荐这么做
那么有没有可以不使用@Param注解,同样也可以传递多个参数(尤其是多个 javaBean)呢?答案是有的,废话不多说,直接上代码

同上,这里只贴出关键部分
DAO 层, UserInfoDao.java

    //    搜索用户,对结果进行分页
   List searchUser(Map<String,Object>);


使用DAO,UserService.java

UserInfo userInfo = new UserInfo();
Pagination page = new Pagination();
Map<String,Object> map = new HashMap<>;
map.put("userInfo",userInfo);
pam.put("page",page);
userService.searchUser(map);

mapper文件userInfomapper.xml

    <select id="searchUser" parameterType="java.util.Map" resultType="UserInfo">
        select *
        from t_userinfo user 
        where 1 =1
        <if test="user.uname != null and ''!= user.uname ">
            and user.uname like '%${userInfo.uname}$%'
        </if>
            
        <if test="page.order != null and page.order == 10" >
            order by user.id asc
        </if>
        limit ${page.pagenum * page.limitnum}, #{page.limitnum}
        
    </select>

作者通过上边的4种情况,主要是为了说明,Mybatis无论是传单个参数,还是传递多个参数,没有必要使用@Param注解啊
使用@param 注解增添了不少代码不说,还容易导致错误,尤其是在 mapper 文件中(paraterType 属性)

以上只是作者的列举的部分代码,源码请看这里: https://github.com/Flying9001/campustore

 

 

<think>我们正在讨论MyBatis中的@Select注解。根据用户的问题,我们需要解释@Select注解的用途和使用方法。 引用[1]提到:@Select是Mybatis的三种继承方式之一(另外两种是@Provider和xml映射文件)。引用[4]展示了一个简单的例子:在接口方法上使用@Select注解并直接写入SQL语句。 引用[3]和[5]展示了更复杂的用法,比如在@Select注解中写动态SQL(使用<script>标签)以及多表连接查询。 因此,我们可以这样组织回答: 1. 用途:@Select注解用于在MyBatis的Mapper接口方法上直接定义SQL查询语句,避免了XML映射文件的编写。 2. 基本用法:在接口方法上添加@Select注解,并在注解内写入SQL语句。 3. 动态SQL:如果需要条件判断等动态SQL,可以使用<script>包裹SQL语句,并在其中使用MyBatis的动态SQL标签(如<if>)。 4. 参数传递:可以通过#{参数名}的方式引用方法参数。如果方法有多个参数,可以使用@Param注解指定参数名。 同时,我们注意到引用[2]提到一个常见错误:当使用IN语句时,如果参数是集合,需要特别注意参数名的指定,否则会出现参数找不到的错误。 因此,在回答中,我们将包括: - 基本示例 - 动态SQL示例 - 参数传递的注意事项 最后,根据系统指令,我们需要在回答末尾生成相关问题。 注意:用户的问题是关于@Select注解的,所以我们聚焦于此。</think>### MyBatis @Select 注解详解 #### 一、用途与作用 `@Select` 是 MyBatis 提供的核心注解之一,主要用于**简化 SQL 映射配置**。其核心作用包括: 1. **替代 XML 映射文件**:直接在 Java 接口方法上编写 SQL 语句,无需额外 XML 文件[^4] 2. **声明查询操作**:标注在 Mapper 接口方法上,声明该方法执行查询操作 3. **支持动态 SQL**:结合 `<script>` 标签实现条件查询(如 `WHERE` 子句动态拼接)[^3] 4. **提高开发效率**:适用于简单 SQL 场景,减少配置复杂度 #### 二、基础使用方法 ```java public interface UserMapper { // 1. 基础查询 @Select("SELECT id, name, age FROM user WHERE id = #{userId}") User getUserById(int userId); // 2. 多参数查询(使用@Param) @Select("SELECT * FROM product WHERE category = #{cat} AND price > #{minPrice}") List<Product> findProducts(@Param("cat") String category, @Param("minPrice") double minPrice); } ``` **参数说明**: - `#{参数名}`:MyBatis 参数占位符,自动防 SQL 注入 - `@Param`:当方法有多个参数时**必须使用**,否则报参数绑定错误[^2] #### 三、动态 SQL 实现 通过 `<script>` 标签支持条件判断: ```java @Select("<script>" + "SELECT * FROM orders WHERE status = &#39;ACTIVE&#39;" + "<if test=&#39;amount != null&#39;> AND total_amount > #{amount} </if>" + "<if test=&#39;startDate != null&#39;> AND create_time >= #{startDate} </if>" + "</script>") List<Order> findActiveOrders(@Param("amount") BigDecimal minAmount, @Param("startDate") Date startDate); ``` **动态标签支持**: - `<if>`:条件判断 - `<foreach>`:循环遍历(常用于 `IN` 语句) - `<choose>/<when>/<otherwise>`:多路选择 #### 四、特殊场景处理 1. **`IN` 语句的正确用法**: ```java @Select("<script>" + "SELECT * FROM camera WHERE id IN " + "<foreach item=&#39;id&#39; collection=&#39;cameraIds&#39; open=&#39;(&#39; separator=&#39;,&#39; close=&#39;)&#39;>" + "#{id}" + "</foreach>" + "</script>") List<Camera> findByIds(@Param("cameraIds") List<Long> ids); // 必须用@Param定义集合名 ``` **避免错误**:直接写 `IN (#{ids})` 会导致 `Parameter &#39;item&#39; not found` 异常[^2] 2. **多表连接查询**: ```java @Select("SELECT u.*, d.department_name " + "FROM user u INNER JOIN department d ON u.dept_id = d.id " + "WHERE u.status = 1") List<UserVO> getActiveUsersWithDept(); ``` #### 五、适用场景与限制 | 场景类型 | 推荐使用 | 注意事项 | |----------------|----------|------------------------------| | 简单静态 SQL | ✅ 推荐 | SQL 长度不宜超过 3 行 | | 复杂动态 SQL | ⚠️ 谨慎 | 需用 `<script>` 维护性较差 | | 多表关联查询 | ⚠️ 谨慎 | 建议拆分为多个方法 | | 大批量结果处理 | ❌ 不推荐 | 需用 XML 配置结果集映射 | > **最佳实践建议**: > - 简单查询(单表操作、固定条件)优先使用 `@Select` > - 复杂业务查询(多表关联、动态条件嵌套)建议使用 XML 映射文件[^1][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值