Mybatis 一对一和一对多查询
首先创建两个实体类(尽量实现全部的getter和setter方法,防止后续出错,此处使用Lombok)
@Data
public class Order {
private Integer no;
private Integer userId;
private Integer goodsId;
private Integer goodsAmount;
}
@Data
public class User {
private Integer id;
private String username;
private String password;
private String tel;
private String address;
}
一对多
这里要在一的一方增加一个多的一方的List集合属性
@Data
public class User {
private Integer id;
private String username;
private String password;
private String tel;
private String address;
//多
private List<Order> orderList;
}
接下来是Mapper.xml
中配置,使用collection
映射多的一方的结果
第一种联表查询方式
此种方式将一
和多
的关联关系写在查询的sql
中,在xml
文件中写sql
结尾不要写分号
<select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder">
SELECT user_tb.*,order_tb.* FROM user_tb,order_tb WHERE user_tb.id=#{id} AND order_tb.user_id=user_tb.id
</select>
<resultMap id="userResultWithOrder" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="tel" column="tel"/>
<result property="address" column="address"/>
<!--多的一方的集合-->
<collection property="orderList" ofType="order">
<id property="no" column="no"/>
<result property="userId" column="user_id" />
<result property="goodsId" column="goods_id" />
<result property="goodsAmount" column="goods_amount" />
</collection>
</resultMap>
第二种子查询方式
此种方式是将多的一方的结果通过单独的查询,将结果返回
<select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder">
SELECT * FROM user_tb WHERE id=#{id}
</select>
<resultMap id="userResultWithOrder" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="tel" column="tel"/>
<result property="address" column="address"/>
<!--此处使用子查询方式,调用子查询返回多的一方结果。通过付`column`设置要关联的字段,传入到子查询中,此处的select属性值依与子查询的id对应-->
<collection property="orderList" column="id" ofType="order" select="queryOrderByUserId"/>
</resultMap>
<!--子查询-->
<select id="queryOrderByUserId" parameterType="integer" resultMap="orderMap">
SELECT * FROM order_tb WHERE user_id=#{id}
</select>
<resultMap id="orderMap" type="order">
<id property="no" column="no"/>
<result property="userId" column="user_id"/>
<result property="goodsId" column="goods_id"/>
<result property="goodsAmount" column="goods_amount"/>
</resultMap>
一对一
一对一也有两种方式,使用association
映射结果
@Data
public class User {
private Integer id;
private String username;
private String password;
private String tel;
private String address;
//一
private Order order;
}
第一种联表查询方式
<select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder">
SELECT user_tb.*,order_tb.* FROM user_tb,order_tb WHERE user_tb.id=#{id} AND order_tb.user_id=user_tb.id
</select>
<resultMap id="userResultWithOrder" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="tel" column="tel"/>
<result property="address" column="address"/>
<!--这里用到的是javaType,与一对多使用ofType不同-->
<association property="order" javaType="order">
<id property="no" column="no"/>
<result property="userId" column="user_id" />
<result property="goodsId" column="goods_id" />
<result property="goodsAmount" column="goods_amount" />
</collection>
</resultMap>
第二种子查询方式
<select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder">
SELECT * FROM user_tb WHERE id=#{id}
</select>
<resultMap id="userResultWithOrder" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="tel" column="tel"/>
<result property="address" column="address"/>
<!--通过付`column`设置要关联的字段,传入到子查询中,此处的select属性值依与子查询的id对应-->
<association property="orderList" column="id" javaType="order" select="queryOrderByUserId"/>
</resultMap>
<!--子查询,此处传入的参数,就是上面的column对应字段的值-->
<select id="queryOrderByUserId" parameterType="integer" resultMap="orderMap">
SELECT * FROM order_tb WHERE user_id=#{id}
</select>
<resultMap id="orderMap" type="order">
<id property="no" column="no"/>
<result property="userId" column="user_id"/>
<result property="goodsId" column="goods_id"/>
<result property="goodsAmount" column="goods_amount"/>
</resultMap>
总结
- 在xml中的type可以使用别名,也可以使用全路径;
select
的id值必须与mapper
接口中方法名一致,可以使用插件防止出错,例如:FreeMybatisPlugin
,MybatisCodeHelper Pro
等- 项目中进行一对多查询时可能也会涉及到扩展类,即不在原基础实体类修改,通过继承的方式,进行属性拓展。如下所示
<resultMap id="Father" type="xxxx">
<result property="name" column="NAME"/>
<result property="volume" column="VOLUME"/>
</resultMap>
<!--通过Extends设置要继承的父类即可,属性值对应父类的resultMap的id值-->
<resultMap id="extendDemo" type="XXXX" extends="Father">
<result property="level1" column="LEVEL1"/>
<result property="level2" column="LEVEL2"/>
</resultMap>
扩展
批量写操作
<insert id="insertUserRoleBatch">
INSERT INTO t_user_role(user_id,role_id)
VALUES
<foreach collection="userRoles" index="index" item="userRole" separator=",">
(#{userRole.userId},#{userRole.roleId})
</foreach>
</insert>
collection:传入集合或数组的名称。
index:遍历数组或集合的索引一般就写index。
item:取出每一个元素的名称。
separator:上一个元素与下一个元素之间填充的字符,如不需要则不添加此属性。
批量查询
此处进行了截取,主要应用的IN
关键字部分,通过传入的集合进行拼接
AND XXXX IN
<foreach collection="clientTypes" index="index" item="clientTypeInt"
open="(" close=")" separator=",">
#{clientTypeInt}
</foreach>
open:表示在每个元素前填充字符。
close:表示在每个元素后填充字符。
模糊查询
locate(#{name,jdbcType=VARCHAR}, t.name)>0
:t.name
数据库字段名,#{name,jdbcType=VARCHAR}
传入的参数值。locate
函数会帮我们实现模糊查询,类似于java
中indexOf
。
查询结果字符串拼接
GROUP_CONCAT(tct.client_name SEPARATOR ‘,’) :连接字符串函数。
tct.client_name :需要连接的字段名。
SEPARATOR ',' :中间连接符。