Mybatis中resultMap配置细则
1、级联属性
在实际的业务场景中,数据库表之间会涉及到一对一、一对多、多对多等多种关系,mybatis中resultMap提供了association、collection这些标签来处理这种关系。
1.1、associaton
association是mybatis支持级联的一部份,association主要是用来解决一对一关系的,假设我现在有两张表,一张表示省份,一张表示省份的别名,假设一个省只有一个别名(实际上有的省份有两个别名),我们来看一下如下两张表。
1.省份表:
说明:area字段表示该省市属于北方还是南方
2.别名表:
别名表中pid表示省份的id,假设我现在有一个实体类,Province,该类有两个属性,一个叫做name表示省份的名字,一个叫做alias表示省份的别名,那么我在查询的时候可以通过association来实现这种一对一级联,实现方式如下:
创建Alias实体类
public class Alias {
private Long id;
private String name;
}
创建Province实体类
public class Province {
private Long id;
private String name;
private Alias alias;
}
创建AliasMapper
public interface AliasMapper {
Alias findAliasByPid(Long id);
}
创建aliasMapper.xml(根据省份的id找到省份的别名)
<?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="org.sang.db.AliasMapper">
<select id="findAliasByPid" parameterType="long" resultType="org.sang.bean.Alias">
SELECT * FROM alias WHERE pid=#{id}
</select>
</mapper>
创建ProvinceMapper
public interface ProvinceMapper {
List<Province> getProvince();
}
创建provinceMapper.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="org.sang.db.ProvinceMapper">
<resultMap id="provinceResultMapper" type="org.sang.bean.Province">
<id column="id" property="id"/>
<association property="alias" column="id" select="org.sang.db.AliasMapper.findAliasByPid"/>
</resultMap>
<select id="getProvince" resultMap="provinceResultMapper">
SELECT * FROM province
</select>
</mapper>
注意:这里的resultMap,我们在resultMap中指定了association节点,association节点中的select属性表示要执行的方法,该方法实际上指向了一条SQL语句(就是我们在aliasMapper.xml中配置的那条SQL语句),column表示给方法传入的参数的字段,我们这里要传入省份的id,所以column为id,property表示select查询的结果要赋值给谁,我们这里当然是赋值给Province的alias属性。
测试
@Test
public void test7() {
SqlSession sqlSession = null;
try {
sqlSession = DBUtils.openSqlSession();
ProvinceMapper pm = sqlSession.getMapper(ProvinceMapper.class);
List<Province> list = pm.getProvince();
for (Province province : list) {
System.out.println(province);
}
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
测试结果
1.2 collection
collection是用来解决一对多级联的,举个例子,每个省份下面有很多城市,如下图所示是一张城市表:
城市表中有一个pid字段,该字段表示这个城市是属于哪个省份的,那么在Province实体类中添加一个属性叫做cities,这个cities属性的数据类型是一个List集合,这个集合中放的所有的数据就是这个省份的,我希望查询结束之后这个属性的值就会被自动填充,以下就是实现步骤:
为Province类添加属性
public class Province {
private Long id;
private String name;
private Alias alias;
private List<City> cities;
}
创建City实体类
public class City {
private Long id;
private Long pid;
private String name;
}
创建CityMapper
public interface CityMapper {
List<City> findCityByPid(Long id);
}
CityMapper中就提供一个方法,那就是根据省份的id来查找到相应的城市。
创建cityMapper.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="org.sang.db.CityMapper">
<select id="findCityByPid" parameterType="long" resultType="org.sang.bean.City">
SELECT * FROM city WHERE pid=#{id}
</select>
</mapper>
provinceMapper.xml添加collection标签
<?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="org.sang.db.ProvinceMapper">
<resultMap id="provinceResultMapper" type="org.sang.bean.Province">
<id column="id" property="id"/>
<association property="alias" column="id" select="org.sang.db.AliasMapper.findAliasByPid"/>
<collection property="cities" column="id" select="org.sang.db.CityMapper.findCityByPid"/>
</resultMap>
<select id="getProvince" resultMap="provinceResultMapper">
SELECT * FROM province
</select>
</mapper>
测试代码
@Test
public void test7() {
SqlSession sqlSession = null;
try {
sqlSession = DBUtils.openSqlSession();
ProvinceMapper pm = sqlSession.getMapper(ProvinceMapper.class);
List<Province> list = pm.getProvince();
for (Province province : list) {
System.out.println(province);
}
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
测试结果