mybatis多参数传递(其中包括数组)

本文介绍了一个MyBatis批量删除操作的具体实现方法。通过Mapper接口定义了批删功能,并在XML文件中配置了对应的SQL语句。该方法接收活动ID及用户ID数组作为参数,实现了对T_ACT_USERS表中相关记录的批量删除。

转载地址:https://blog.youkuaiyun.com/baochanghong/article/details/51460545

mapper接口的方法:

[java]  view plain  copy
  1. public void batchDelete(@Param(value = "activityId") Integer activityId, @Param(value = "userIds") Integer[] userIds);  

mapper.xml的配置:

[html]  view plain  copy
  1. <insert id="batchDelete">  
  2.      delete from T_ACT_USERS where ACTIVITY_ID = #{activityId}  
  3.      and USER_ID in  
  4.      <foreach collection="userIds" item="item" index="index" open="(" separator="," close=")">  
  5.             #{item}  
  6.      </foreach>  
  7. </insert>  
<think>我们想要实现多表关联查询,并将其中一个表的数据组合成数组。在MyBatis中,可以通过两种主要方式实现:使用嵌套结果映射(通过JOIN一次性查询)或使用嵌套查询(分多次查询)。这里我们重点讨论如何将关联表的数据聚合成数组。假设有两个表:用户表(user)和订单表(order),一个用户可以有多个订单。我们想要查询用户信息,并将该用户的所有订单信息聚合成一个数组(或List)作为用户对象的一个属性。有两种方法可以实现:1.使用嵌套结果映射(JOIN查询):通过一次SQL查询,使用JOIN连接多个表,然后在结果映射中使用`<collection>`(在XML中)或`@Result`配合`@Many`(在注解中)将关联的多个订单组合成一个集合。2.使用嵌套查询:先查询用户,然后根据用户id去查询订单,然后将订单集合设置到用户对象中。由于问题要求使用注解,我们将使用注解方式实现。步骤:1.定义实体类:-User类包含用户的基本信息和订单列表(List<Order>)- Order类包含订单信息2.在Mapper接口中,使用@Select注解编写SQL,使用@Results注解定义结果映射,其中订单集合使用`@Result`注解的`many`属性配合`@Many`注解来映射。示例代码:实体类:```javapublicclass User{private Integerid;privateString name;//其他用户字段...//订单列表,使用@TableField(exist=false)等注解标记非数据库字段(如果需要)privateList<Order>orders;//gettersand setters...} publicclass Order{private Integerid;privateStringorderNumber;//其他订单字段...//gettersand setters...} ```Mapper接口中的方法:```javapublicinterface UserMapper {@Select("SELECT u.* FROMuser uWHERE u.id =#{id}")@Results({@Result(property= "id",column ="id", id= true),@Result(property= "name",column ="name"),//其他用户字段的映射...//重点:映射订单集合,使用@Many注解指定查询订单的方法,column参数指定传递给子查询的列(这里是用户id)@Result(property= "orders",column ="id", many= @Many(select ="selectOrdersByUserId"))})UserfindUserWithOrders(int id);//根据用户ID查询订单@Select("SELECT *FROM `order`WHERE user_id =#{userId}")List<Order>selectOrdersByUserId(int userId); }```这样,当我们调用`findUserWithOrders`方法时,MyBatis会先执行主查询(根据id查询用户),然后根据主查询结果中的id列(通过column="id"指定)去执行子查询`selectOrdersByUserId`,并将查询得到的订单列表设置到User对象的orders属性中。注意:这种方式会产生N+1查询问题(如果查询多个用户,则每个用户都会触发一次订单查询)。如果希望一次性通过JOIN查询解决,可以使用嵌套结果映射(一次查询,然后手动映射结果集)。但注解方式对于嵌套结果映射的支持相对复杂,需要手动指定每一列的映射关系。使用JOIN查询的注解方式示例: ```java@Select("SELECTu.idasuser_id,u.name,o.idas order_id,o.order_number "+"FROMuser uLEFT JOIN`order`o ONu.id= o.user_id" +"WHERE u.id =#{id}") @Results({@Result(property ="id", column= "user_id", id= true),@Result(property= "name",column ="name"),//使用@Result映射集合,这里使用@Many注解,但是注意,在嵌套结果映射中,我们需要指定如何将结果集中的多行数据组合成集合//实际上,在注解中,MyBatis没有提供像XML中<collection>那样直接处理嵌套结果的方式,所以通常我们使用嵌套查询(如上)或者使用ResultMap的继承(需要定义在XML中)来避免重复。//但是,我们可以通过@Result注解的many属性结合@Many注解来指定嵌套结果映射,不过这种方式在注解中并不直接支持将单次JOIN查询的结果拆分成多个对象并组合成集合。//因此,在注解中,对于一对多的嵌套结果映射(一次JOIN查询),我们通常需要借助额外的工具类或者手动处理,或者使用MyBatis的@ResultMap注解引用XML中定义的ResultMap。//所以,在注解中,更常见的做法是使用嵌套查询(分两次查询)来实现一对多映射,尽管有N+1问题,但对于单个用户查询是可以接受的。}) UserfindUserWithOrdersByJoin(int id); ```由于注解方式在嵌套结果映射(一次JOIN查询)上支持不够完善,对于复杂的一对多映射,建议使用XML配置方式。但如果我们坚持使用注解,并且希望避免N+1查询,我们可以使用`@ResultMap`注解来引用在XML中定义的ResultMap(如果项目允许混合使用注解和XML)。另一种思路:我们可以编写一个SQL,通过GROUP_CONCAT等函数将多个订单的信息拼接成一个字符串,然后在Java中解析成数组。但这种方法不推荐,因为破坏了数据的结构。因此,对于注解方式,我们通常采用嵌套查询(多次查询)的方式来实现一对多映射,将关联表的数据聚合成数组(或集合)。总结:使用`@Many`注解配合子查询方法,将关联表的数据查询出来并设置到集合属性中,从而实现聚合为数组(集合)的效果。相关问题:1.如何解决MyBatis中的N+1查询问题?2.在MyBatis注解中如何实现多表联合查询的结果映射?3. MyBatis注解和XML配置方式各有什么优缺点?</think>### 如何在 MyBatis 中将多表关联数据聚合为数组MyBatis 中实现多表关联查询并将关联表的数据聚合为数组,可以通过以下两种主要方式实现: #### 方法一:使用嵌套查询(Nested Query) 通过 `@Many` 注解实现一对多关联,将关联表的数据自动封装为集合类型(数组/List): ```java // 主查询方法 @Select("SELECT * FROM users WHERE id = #{userId}") @Results({ @Result(property = "userId", column = "id"), @Result(property = "userName", column = "name"), @Result(property = "orders", column = "id", many = @Many(select = "findOrdersByUserId")) }) User getUserWithOrders(int userId); // 子查询方法 @Select("SELECT * FROM orders WHERE user_id = #{userId}") Order[] findOrdersByUserId(int userId); ``` **关键点说明:** 1. `@Many` 注解声明一对多关系 2. `select` 属性指向子查询方法 3. `column = "id"` 将主查询的 `id` 值传递给子查询 4. 子查询返回类型声明为 `Order[]`(数组)或 `List<Order>` 5. 主实体类需包含数组成员: ```java public class User { private int userId; private String userName; private Order[] orders; // 数组成员 } ``` #### 方法二:使用 JOIN 查询 + 结果映射 通过单次 SQL 查询获取所有数据,手动映射到复合对象: ```java @Select("SELECT u.id AS userId, u.name AS userName, " + "o.id AS orderId, o.product " + "FROM users u " + "LEFT JOIN orders o ON u.id = o.user_id " + "WHERE u.id = #{userId}") @Results({ @Result(property = "userId", column = "userId"), @Result(property = "userName", column = "userName"), @Result(property = "orders", column = "userId", many = @Many(select = "findOrdersByUserId")) }) UserOrders getUserOrders(int userId); ``` **实体类设计:** ```java public class UserOrders { private int userId; private String userName; private Order[] orders; // 聚合为数组 // 使用@TableField标记非表字段 @TableField(exist = false) private Order[] temporaryOrders; } ``` #### 结果处理技巧 1. **数组初始化**:在映射器中初始化数组避免空指针 ```java @Result(property = "orders", column = "userId", many = @Many(select = "findOrdersByUserId"), javaType = Order[].class) // 明确指定数组类型 ``` 2. **空结果处理**:使用 MyBatis 的 `@Result` 配置 ```java @Result(property = "orders", column = "userId", many = @Many(select = "findOrdersByUserId"), nullValueProperty = "new Order[0]") // 空结果返回空数组 ``` 3. **动态过滤**:在子查询中添加条件 ```java @Select("SELECT * FROM orders WHERE user_id = #{userId} AND status = 'ACTIVE'") Order[] findActiveOrdersByUserId(int userId); ``` #### 性能优化建议 1. 对于大数据量,优先使用 JOIN 查询减少数据库访问次数 2. 启用 MyBatis 二级缓存减少重复查询 ```xml <settings> <setting name="cacheEnabled" value="true"/> </settings> ``` 3. 使用 `@Options` 配置缓存 ```java @Select("SELECT * FROM users...") @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE) ``` #### XML 等价实现 若需 XML 配置,等价实现如下: ```xml <select id="getUserWithOrders" resultMap="userOrdersMap"> SELECT * FROM users WHERE id = #{userId} </select> <resultMap id="userOrdersMap" type="User"> <id property="userId" column="id"/> <result property="userName" column="name"/> <collection property="orders" column="id" select="findOrdersByUserId" ofType="Order[]"/> </resultMap> <select id="findOrdersByUserId" resultType="Order"> SELECT * FROM orders WHERE user_id = #{userId} </select> ``` [^1]: [^2]: [^3]:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值