Mybatis中collection和association的使用

Mybatis中的collection标签中的javaType和ofType属性的区别
在使用mybatis时,有时候需要在数据库中进行关联查询(left/right join)来根据某个字段获取到另一个表的的一个List集合。在配置resultMap时,需要用到collection标签对这个LIst属性进行映射:比如在部门表中有一个列表List存放这个表中的所有员工,javaBean如下:
public class Department {

	private Integer id;
	private String departmentName;
	private List<Employee> emps;
}
123456
员工表如下:
public class Employee {

	private Integer id;
	private String lastName;
	private String email;
	private String gender;
}
1234567
用mybatis对这两个表进行关联查询查询:
<select id="getDeptByIdPlus" resultMap="MyDept">
		SELECT d.id did, d.dept_name dept_name,
			e.id eid, e.last_name last_name, e.email email,e.gender gender
		FROM department d
		LEFT JOIN employee e
		ON d.id = e.d_id
		WHERE d.id = 1
</select> 
12345678
由于是通过关联查询得到的这个List,所以此时需要用到resultMap标签对返回值的类型进行自定义:
<resultMap type="bean.Department" id="MyDept">
		<id column="did" property="id"/>
		<result column="dept_name" property="departmentName"/>
		<!-- 
			collection定义关联的集合类型的属性的封装规则:
			property="emps":指定这是哪个集合属性,这里为那个集合属性emps
			ofType:指定集合内封装的JavaBean类型(集合内装的什么),这里即为Employee类
		 -->
		<collection property="emps" ofType="bean.Employee">
			<!-- 定义集合中元素的封装规则 -->
			<id column="eid" property="id"/>
			<result column="last_name" property="lastName"/>
			<result column="email" property="email"/>
			<result column="gender" property="gender"/>
		</collection>
</resultMap>
12345678910111213141516
在这个resultMap 标签中,用collection这个子标签对这个List进行映射。通过Alt+/可以发现,collection标签中包含两个关于javaBean的Type属性分别是ofType和javaType。其中ofType指定的这个List所存放的javaBean的类型,比如这里就是Employee类型。而javaType指定的当前这个配置的标签所对应的属性,比如我们这里的collection配置的是一个List,就可以配置成javaType=“java.util.ArrayList”(此处没写)。

*collection和association的使用总结:
关于标签association和collection相同点和不同点如图所示:测试结果集
在这里插入图片描述
(一)准备阶段
(1)实体类(User)
package com.jyk.entity;
public class User {
    private Integer id;
    private String name;
    private String password;
    private Address address;

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", address=" + address +
                '}';
    }
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
(2)实体类Address
package com.jyk.entity;

/**
 * @Classname Address
 * @Description TODO
 * @Date 2020/7/11 10:50
 * @Created by JYK
 */
public class Address {
    private Integer addno;
    private String city;
    private String county;
    private String town;

    public Integer getAddno() {
        return addno;
    }

    public void setAddno(Integer addno) {
        this.addno = addno;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getCounty() {
        return county;
    }

    public void setCounty(String county) {
        this.county = county;
    }

    public String getTown() {
        return town;
    }

    public void setTown(String town) {
        this.town = town;
    }

    @Override
    public String toString() {
        return "Address{" +
                "addno=" + addno +
                ", city='" + city + '\'' +
                ", county='" + county + '\'' +
                ", town='" + town + '\'' +
                '}';
    }
}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
(二)测试阶段(xml文件配置)
association
<resultMap id="userid" type="com.jyk.entity.User">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="password" column="password"></result>
        <association property="address" javaType="com.jyk.entity.Address" >
            <id property="addno" column="addno"></id>
            <result property="city" column="city"></result>
            <result property="county" column="country"></result>
            <result property="town" column="town"></result>
        </association>
    </resultMap>
    <select id="selectById" resultMap="userid">
        select * from user left join address on address.addno=user.id where id=#{id}
    </select>
1234567891011121314
collection
<resultMap id="userid" type="com.jyk.entity.User">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="password" column="password"></result>
        <collection property="address" ofType="com.jyk.entity.Address">
            <id property="addno" column="addno"></id>
            <result property="city" column="city"></result>
            <result property="town" column="town"></result>
            <result property="county" column="county"></result>
        </collection>
    </resultMap>
    <select id="selectById" resultMap="userid">
        select * from user left join address on user.id=address.addno where id=#{id}
    </select>
1234567891011121314
association测试结果collection测试结果因此得出结论:一些场景下,association和collection两者都可以满足需求,达到关联查询的效果,使用两者任意一个标签都可以,具体情况具体分析,以需求为导向实现相应需求。使用任何标签其实都无所谓,只要能满足需求即可。
在这里插入图片描述
在这里插入图片描述
(四)不同点案例及测试
collection属性值包含:association标签属性值包含:因此ofType成为,ofType为collection传入的类型,javaType为返回值类型,例如下图,ofType=Address(完全限定名),javaType=List(完全限定名)。实体类对象:表示一个人可以有多个收货地址 BaseDao.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.jyk.dao.BaseDao">

    <resultMap id="userid" type="com.jyk.entity.User">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="password" column="password"></result>
        <!--另外一个dao层的接口-->
        <collection property="addresses" ofType="com.jyk.entity.Address" column="id" javaType="java.util.List" fetchType="lazy" select="com.jyk.dao.AddressDao.selectaddId">
        </collection>
    </resultMap>
    <select id="selectById" resultMap="userid">
        select * from user where id=#{id}
    </select>

    <select id="selectAll" resultType="com.jyk.entity.User" >
        select * from test
     </select>
    <insert id="insert" parameterType="com.jyk.entity.User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
        insert into user(name,password) values (#{name},#{password})
    </insert>
    <update id="update" parameterType="com.jyk.entity.User" useGeneratedKeys="true" keyProperty="id">
        update user set name=#{name},password=#{password} where id=#{id}
    </update>

<!--    <delete id="delete" >-->
<!--        delete from test where id=#{id} and name=#{name}-->
<!--    </delete>-->

</mapper>

12345678910111213141516171819202122232425262728293031323334
AddressDao.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.jyk.dao.AddressDao">
    <select id="selectaddId" resultType="com.jyk.entity.Address">
        select * from address where addno=#{addno}
    </select>
</mapper>
123456789
最终实验结果:
在这里插入图片描述
总结:
出错点:(1).xml的文件和dao层接口的文件名称需要一致,在mybatis-config.xml中使用的是package扫描。这一块需要注意算法题:(1)求一个数中二进制1的个数思路:使用N&(~(N)+1)求最右侧为1的位数
在这里插入图片描述
public class Demo {
    public static void main(String[] args) {
        int count = getCount(15);
        System.out.println(count);
    }
    public static int getCount(int N){
        int count=0;
        while (N!=0){
            count++;
            N^=(N&((~N)+1));
        }
        return count;
    }
}
1234567891011121314
(2)一个数组中,只有一个数出现奇数,其他数都是偶数,求此数为多少?(思路:异或)
在这里插入图片描述
public int number(int[]arr){
	int result = 0;
	for(int i=0;i<arr.length;i++){
		result^=arr[i];
	}
	return result;
}

mybatis中association和collection的column传入多个参数值
项目中在使用association和collection实现一对一和一对多关系时需要对关系中结果集进行筛选,如果使用懒加载模式,即联合使用select标签时,主sql和关系映射里的sql是分开的,查询参数传递成为问题。
mybatis文档:
propertydescriptioncolumn数据库的列名或者列标签别名。与传递给resultSet.getString(columnName)的参数名称相同。注意: 在处理组合键时,您可以使用column=“{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套查询语句。这就会把prop1和prop2设置到目标嵌套选择语句的参数对象中。
<resultMap id="findCountryCityAddressMap" type="map">
    <result property="country" column="country"/>
    <collection property="cityList"
                column="{cityId=city_id,adr=addressCol, dis=districtCol}" //adr作为第二个sql查询条件key,即prop1属性
                ofType="map"                                              //addressCol即为虚拟列名
                javaType="java.util.List" select="selectAddressByCityId"/>
</resultMap>

<resultMap id="selectAddressByCityIdMap" type="map">
    <result property="city" column="city"/>
    <collection property="addressList" column="city" ofType="map" javaType="java.util.List">
        <result property="address" column="address"/>
        <result property="district" column="district"/>
    </collection>
</resultMap>

<select id="findCountryCityAddress" resultMap="findCountryCityAddressMap">
    SELECT
        ct.country,
        ci.city_id,
        IFNULL(#{addressQuery},'') addressCol, //为传入查询条件,构造虚拟列,虚拟列为查询条件参数值
        IFNULL(#{districtQuery},'') districtCol
    FROM
        country ct
    LEFT JOIN city ci ON ct.country_id = ci.country_id
    ORDER BY ct.country_id
</select>

<select id="selectAddressByCityId" parameterType="java.util.Map" resultMap="selectAddressByCityIdMap">
    SELECT
        ci.city,
        ads.address,
      ads.district
    FROM
        (
            SELECT
                city,
                city_id
            FROM
                city ci
            WHERE
                ci.city_id = #{cityId}
        ) ci
    LEFT JOIN address ads ON ads.city_id = ci.city_id
    <where>
        <if test="adr!=null and adr!=''">
            and ads.address RegExp #{adr}
        </if>
        <if test="dis!=null and dis!=''">
            ads.district Regexp #{dis}
        </if>
    </where>

</select>
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
测试文件:
@Test
public void findCountryCityAddressTest() throws JsonProcessingException {
    Map<String,Object> param = new HashMap<>();
    param.put("addressQuery","1168");
    List<Map<String, Object>> rs = countryManager.findCountryCityAddress(param);
    ObjectMapper mapper = new ObjectMapper();
    ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
    System.out.println(writer.writeValueAsString(rs));
}
123456789
测试结果:
[
    {
        "country": "Afghanistan",
        "cityList": [{
                "city": "Kabul",
                "addressList": [{
                        "address": "1168 Najafabad Parkway",
                        "district": "Kabol"
                    }
                ]
            }
        ],
        "city_id": 251
    },
    {
        "country": "Algeria",
        "cityList": [],
        "city_id": 59
    }
]
1234567891011121314151617181920
可以看到,确实将查询条件通过column参数传入到第二个sql中,并执行成功

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值