对象关系分类
泛化关系,实现关系,依赖关系,关联关系,聚合关系,组合关系
使用最多的就是关联关系
单向多对一保存的关系
例子:保存一个部门和两个员工,两个员工属于这个部门
所以需要在员工里面有一个部门的属性
创建员工和部门两个实体类
public class Employee {
private Long id;
private String name;
//关联属性
private Dept dept;
}
此时部门表和员工表都需要同时进行插入数据
将部门的id同时插入到员工表里面,此时只需要给附表添加取主键的属性
deptMapper.xml
<!--
useGeneratadKeys="true":获取数据保存数据的主键值
keyProperty="id": 列名
-->
<insert id="insert" useGeneratadKeys="true" keyProperty="id">
insert into dept values(#{name})
</insert>
EmployeeMapper.xml,可以使用里面的dept属性获取部门的id
<!--主表不用给抽主键的值--><insert id="insert" parameterType="cn.wolfcode.mapper.EmployeeMapper" >insert into employee (name,dept_id) values(#{name},#{dept.dept_id})</insert>
在测试类里面需要先保存部门才能在保存员工,这样才有部门的id值可以进行返回,穿进去的是一个员工对象
/*** 添加员工并且使用从表添加部门编号*/
@Testpublic void insert(){SqlSession session = MybatisUtil.getSession();DeptMapper deptMapper = session.getMapper(DeptMapper.class);Dept dept = new Dept();dept.setDept_name("研发部");//先保存部门deptMapper.insert(dept);//这里会返回部门的id,可以使用dept.getid()获取部门的idEmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);Employee employee1 = new Employee();employee1.setName("小小");employee1.setDept(dept);Employee employee2 = new Employee();employee2.setName("灰灰");employee2.setDept(dept);//保存员工employeeMapper.insert(employee1);employeeMapper.insert(employee2);session.commit();session.close();
单向多对一额外sql查询使用的resultMap标签
方式1,直接使用属性的里面的值,重新给查询结果添加别名
<resultMap id="emp_resultMap" type="cn.wolfcode.domain.Emp"><id column="id" property="id"></id><result column="name" property="name"></result><result column="did" property="dept.id"></result><result column="dname" property="dept.name"></result></resultMap>
<select id="selectById" resultType="cn.wolfcode.domain.Emp" resultMap="emp_resultMap">select e.id,e.`name`,d.id did,d.`name` dnamefrom employee ejoin department don e.dept_id=d.idwhere e.id=#{id}</select>
方式2
使用多对一查询的时候需要使用sql中的resultMap标签
例子:查询员工及员工的部门
部门表不需要要进行任何处理
<resultMap id="selectAll" type="cn.wolfcode.domain.Employee"><id column="id" property="id"></id><result column="name" property="name"></result><association property="dept" javaType="cn.wolfcode.domain.Dept" ><id column="dept_id" property="dept_id"></id><result column="dept_name" property="dept_name"></result></association>
</resultMap><select id="select" resultType="cn.wolfcode.domain.Employee" resultMap="selectAll">select name,employee.dept_id ,dept.dept_name from employee join dept on employee.dept_id=dept.dept_id</select>
resultMap标签及其作用
作用:用于自定义实体类与数据库查询结果集之间的映射关系,可以使用该标签实现查询返回的多个列
参数含义:
<resultMap id="selectAll" type="cn.wolfcode.domain.Employee"><id column="id" property="id"></id><result column="name" property="name"></result>
id:给这个resulMap明一个别名
type:这个resoutMap的映射类型
<id column="id" property="id"></id>
表示主键字段或者属性在数据库中的列名
colum:查询出来的列名的名字,可以重新命名
property:主键对应的实体类属性名
<result column="name" property="name"></result>
表示普通字段或者属性在数据库中的列名
colum:查询出来的列名的名字,可以重新命名
property:实体类的普通属性名
association标签
他是在resultMap标签之中的,一个表查一个的时候使用association
<association property="dept" javaType="cn.wolfcode.domain.Dept" ><id column="dept_id" property="dept_id"></id><result column="dept_name" property="dept_name"></result></association>
在单向多对一查询使用,即一个属性通过另一个sql查询的实体类对象得到
property:指定当前属性在这个实体类中对应的那一个属性名,一般这个属性是由另一个实体类定义而来
javaType:定义这个属性名的实体类的全限定名
里面的,标签就对应这个表名的列名和这个实体类的属性
collection标签
他是在resultMap标签之中的,求list集合的时候使用collection
<resultMap id="stu_teacher_resultMap" type="cn.wolfcode.domain.Stu"><!--id标签表示的主键--><id property="id" column="id"></id><result property="name" column="name"></result><!--property:stu中的属性ofType:teachers本身的类型javaType:teachers在stu中的类型--><collection property="teachers" javaType="list" ofType="cn.wolfcode.domain.Teacher"><id property="id" column="tid"></id><result property="name" column="tname"></result></collection></resultMap><!--使用resoutMap进行查询-->
<select id="get" resultType="cn.wolfcode.domain.Stu" resultMap="stu_teacher_resultMap">select stu.*,teacher.id tid,teacher.name tnamefrom stujoin stu_teacheron stu.id=stu_teacher.sidjoin teacheron stu_teacher.tid=teacher.idwhere stu.id=#{id}</select>
在一对多或者多对多查询的时候使用,一个属性有多个关联的是实体类对象
property:指定当前关联的实体对象属性
javaType:定义这个属性名的实体类的全限定名
oftype:指定集合元素的类型,使用这个自定义属性名的全限定名
select:指定执行sql语句的id(就是其他xxxMapper中的接口中的方法名,和这个属性相互对应)
<resultMap id="stu_resoutMap" type="cn.wolfcode.domain.Stu"><id property="id" column="id"></id><result property="name" column="name"></result><!--这里的select关联到teacher上的查询条件,将这个id传到另一个mapper--><collection column="id" property="teachers" select="cn.wolfcode.mapper.TeacherMapper.queryByStudentid" /></resultMap>
column="id"
:指定了当前对象在 SQL 语句查询结果集中的列名,这个列名用于匹配关联对象的外键
property="teachers"
:指定了当前对象(即父对象)中集合类型属性的名称,也就是要将关联对象赋值给哪个属性。
select:这里使用了另一个 Mapper 接口中定义的 ID 为 “queryByStudentid” 的查询方法。
什么是n+1问题及解决办法
出现的原因:若某个查询条件反回了多个结果,并且这些结果又对应了另外一个查询条件的多行结果,此时就会发生n+1次查询的情况
**解决办法:**一般使用关联查询,将多张表进行联合起来进行查询,避免单独查询利用标签和