mybatis05_对应关系
一、一对一关系
以身份证和人为例
1、resultType实现
使用resultType实现,将所需要的属性放到一个实体类中。
⬇️创建数据表
CREATE TABLE `id_card` (
`id` int NOT NULL AUTO_INCREMENT,
`card_num` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`person_id` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE `person` (
`id` int NOT NULL AUTO_INCREMENT,
`person_name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
⬇️实体类 Person
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class Person {
private Integer id;
private String personName;
}
⬇️实体类 IdCard 继承自 Person 使 IdCard 中可以获得 Person中的对象信息;重写 toString 调用父类Person的方法获得 personName。
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class IdCard extends Person{
private Integer id;
private String cardNum;
@Override
public String toString() {
return "IdCard{" +
"cardNum='" + cardNum + '\'' + "personName=" + super.getPersonName() +
'}';
}
}
⬇️mapper映射
<select id="list" resultType="com.ls.pojo.IdCard">
select card_num cardNum,person_name personName
from id_card
join person
on id_card.id = person.id
</select>
⬇️测试
private static void testList() {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.getSqlSession();
IdCardMapper idCardMapper = sqlSession.getMapper(IdCardMapper.class);
List<IdCard> cardList = idCardMapper.list();
cardList.stream().forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {sqlSession.close();}
}
}
⬇️编译后的sql语句和结果
2、resultMap实现
使用 resultType 实现的方式,无非就是将要获取的信息数据字段,都对应到一个扩展 Bean 中,同时还要保持字段名与列名保持一致。这里我们让 IdCardExtends 来获得 IdCard2 的信息(继承),并重写 IdCard 的 toString方法让其能够表现出父类(super)的属性。
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class IdCard2 {
private Integer id;
private String cardNum;
}
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class IdCardExtends extends IdCard2{
Person person;
@Override
public String toString() {
return "IdCardExtends{" +
"person=" + person + "super:"+super.toString()+
'}';
}
}
⬇️定义 resultMap 和 sql 语句
注意指明是哪张表的 id 不然会有Column 'id' in field list is ambiguous。(顺便问一句万能的网友为什么把这个 id_card.id 属性列去掉筛选出来的就全是 null 呢)
使用 association 映射关联查询单个对象的信息
property 属性:要将关联查询的对象信息映射到 person 对象的哪个属性上
javaType 属性:要将关联查询的对象信息映射成哪种 Java 类
<resultMap id="IdCardMap" type="com.ls.pojo.IdCardExtends">
<id property="id" column="id"></id>
<result property="cardNum" column="card_num"></result>
<association property="person" javaType="com.ls.pojo.Person">
<id column="id" property="id"></id>
<result column="person_name" property="personName"></result>
</association>
</resultMap>
<select id="list2" resultMap="IdCardMap">
select id_card.id,card_num cardNum, person_name personName
from id_card
join person
on id_card.id = person.id
</select>
⬇️测试程序
private static void testList2() {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.getSqlSession();
IdCardMapper idCardMapper = sqlSession.getMapper(IdCardMapper.class);
List<IdCardExtends> cardListExtends = idCardMapper.list2();
cardListExtends.stream().forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {sqlSession.close();}
}
}
⬇️
二、一对多关系
以部门与员工之间的关系为例
如果不使用框架进行一对多的联合查询则需要:先调用 dao 层查询部门表,然后再根据部门表与员工表的主外键关联字段,再调用员工表的 dao 再查询员工表数据,最终完成数据组装。
⬇️使用到的数据库如下
CREATE TABLE `emp` (
`emp_id` bigint NOT NULL AUTO_INCREMENT,
`emp_name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`email` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`dept_id` bigint DEFAULT NULL,
PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE `dept` (
`dept_id` bigint NOT NULL AUTO_INCREMENT,
`dept_name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`location` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
⬇️实体类有部门和员工两个,其中部门中应有一个List的员工列表作为其属性
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class Dept {
private Long deptId;
private String deptName;
private String location;
//一个部门多个员工
private List<Emp> empList;
}
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@Data
@Accessors(chain = true)
public class Emp {
private Long empId;
private String empName;
private String address;
private String email;
private Date createTime;
private Date updateTime;
private Long deptId;
}
⬇️mapper映射文件,配置关联查询 Orders 信息的映射,使用 collection 映射关联查询多个对象的信息
property 属性:要将关联查询的对象信息映射到 ordersUser 对象的哪个属性上
ofType 属性:要将关联查询的对象信息映射成哪种 Java 类
import com.ls.pojo.Dept;
import com.ls.pojo.Emp;
import java.util.List;
public interface DeptMapper {
/**
* 根据部门id查部门的信息
* 包括部门的员工的信息
* @param deptId
* @return
*/
List<Dept> findById(Long deptId);
}
<resultMap id="DeptMap" type="com.ls.pojo.Dept">
<id property="deptId" column="dept_id"></id>
<result property="deptName" column="dept_name"></result>
<result property="location" column="location"></result>
<collection property="empList" ofType="com.ls.pojo.Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="address" property="address"></result>
<result column="create_tiem" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</collection>
</resultMap>
<select id="findById" resultMap="DeptMap">
select emp.*,dept.* from dept join emp
on dept.dept_id = emp.dept_id
where dept.dept_id = #{deptId}
</select>
⬇️测试
这里以根据 id 查询部门信息为例,部门信息中应该包含所有员工的信息
private static void testFindById() {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.getSqlSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
List<Dept> deptList = deptMapper.findById(1L);
deptList.stream().forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {sqlSession.close();}
}
}
⬇️测试结果
三、多对多关系
暂时略,毕竟联合查询降低性能,日后面试题补上。