mybatis--关系映射

在讲之前,先把javaBean列出来. 因为下面一直在用:

public class Employee {
   private Integer id;
   private String lastName;
   private String email;
   private String gender;
 
   public Employee() {
      super();
   } 
   public Employee(Integer id, String lastName, String email, String gender) {
      super();
      this.id = id;
      this.lastName = lastName;
      this.email = email;
      this.gender = gender;
   }
 
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   public String getLastName() {
      return lastName;
   }
   public void setLastName(String lastName) {
      this.lastName = lastName;
   }
   public String getEmail() {
      return email;
   }
   public void setEmail(String email) {
      this.email = email;
   }
   public String getGender() {
      return gender;
   }
   public void setGender(String gender) {
      this.gender = gender;
   }
   @Override
   public String toString() {
      return "Employee [id=" + id + ", lastName=" + lastName + ", email="
            + email + ", gender=" + gender + "]";
   }

1.resultType


 从这条语句中返回的期望类型的类的完全限定名或别名,如果是集合,应该是集合可以包含的类型.而不是集合本身,此属性和resultMap,不能同时使用

使用1: 返回值是list类型

<!-- public List<Employee> getEmpsByLastNameLike(String lastName); -->
<!--resultType:如果返回的是一个集合,要写集合中元素的类型  -->
<select id="getEmpsByLastNameLike" resultType="com.kwy.mybatis.bean.Employee">
   select * from tbl_employee where last_name like #{lastName}
</select>

使用2: 单条记录封装一个map

//返回一条记录的map;key就是列名,值就是对应的值
<!--public Map<String, Object> getEmpByIdReturnMap(Integer id);  -->
<select id="getEmpByIdReturnMap" resultType="map">
 	select * from tbl_employee where id=#{id}
</select>
mybatis已经为常用的类起了别名,map就是其中一个

使用3:多条记录封装一个map

//多条记录封装一个map:Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean
//@MapKey:告诉mybatis封装这个map的时候使用哪个属性作为map的key
@MapKey("lastName")
public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);
<!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName);  -->
<select id="getEmpByLastNameLikeReturnMap" resultType="com.kwy.mybatis.bean.Employee">
   select * from tbl_employee where last_name like #{lastName}
</select>
resultType是和自动封装有关, 指定封装什么类型, 数据就封装成什么类型.如果查出来的列名,和javaBean属性名不一样,那么一开始就封装不成功的. 解决办法是,1.写了别名; 2.如果列名和javaBean属性名符合驼峰命名,我们就开启驼峰命名就好了.3.自定义结果集resultMap

2.resultMap

外部resultMap的命名引用,和resultType不能同时使用

简单使用

<!--  public Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
   select * from tbl_employee where id=#{id}
   <if test="_parameter!=null">
      and 1=1
   </if>
</select>
更强大的走起: 

如果我们的javaBean------Employee中添加了一个部门的属性
 
 
public class Employee {
   
   private Integer id;
   private String lastName;
   private String email;
   private String gender;
  //部门属性
   private Department dept;
   
   public Employee() {
      super();
   }
   
   public Employee(Integer id, String lastName, String email, String gender) {
      super();
      this.id = id;
      this.lastName = lastName;
      this.email = email;
      this.gender = gender;
   }
   
   public Department getDept() {
      return dept;
   }

   public void setDept(Department dept) {
      this.dept = dept;
   }
   
   ......

javaBean-------Department

public class Department {
   
   private Integer id;
   private String departmentName;
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   public String getDepartmentName() {
      return departmentName;
   }
   public void setDepartmentName(String departmentName) {
      this.departmentName = departmentName;
   }
   @Override
   public String toString() {
      return "Department [id=" + id + ", departmentName=" + departmentName
            + "]";
   }
场景一

查询Employee的同时查询员工对应的部门

一个员工有与之对应的部门信息;

id  last_name  gender    d_id     did  dept_name (private Department dept;)

1.联合查询: 采用级联属性封装结果集

<select id="getEmpAndDept" resultMap="MyDifEmp">
   SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
   d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
   WHERE e.d_id=d.id AND e.id=#{id}
</select>
<resultMap type="com.kwy.mybatis.bean.Employee" id="MyDifEmp">
   <id column="id" property="id"/>
   <result column="last_name" property="lastName"/>
   <result column="gender" property="gender"/>
   <result column="did" property="dept.id"/>
   <result column="dept_name" property="dept.departmentName"/>
</resultMap>

2.使用association定义关联的单个对象的封装规则;

 
 
<resultMap type="com.kwy.mybatis.bean.Employee" id="MyDifEmp2">
   <id column="id" property="id"/>
   <result column="last_name" property="lastName"/>
   <result column="gender" property="gender"/>
   
   <!--  association可以指定联合的javaBean对象,一个复杂的类型关联;许多结果将包成这种类型
   ----嵌入结果映射-结果映射自身的关联;
   property="dept":指定哪个属性是联合的对象
   javaType:指定这个属性对象的类型[不能省略]
   -->
   <association property="dept" javaType="com.kwy.mybatis.bean.Department">
      <id column="did" property="id"/>
      <result column="dept_name" property="departmentName"/>
   </association>
</resultMap>
上面这种是使用的association的嵌套结果集,还可以使用它的分步查询
我们在现实的开发中,有department表,就会有department的mapper. 也会有根据id来查询部门.
1: 按照员工id查询员工信息
2.根据查询员工信息中的d_id值去部门表查出部门信息

3.部门设置到员工中

<!--  id  last_name  email   gender    d_id   -->
<resultMap type="com.kwy.mybatis.bean.Employee" id="MyEmpByStep">
   <id column="id" property="id"/>
   <result column="last_name" property="lastName"/>
   <result column="email" property="email"/>
   <result column="gender" property="gender"/>
   <!-- association定义关联对象的封装规则
      select:表明当前属性是调用select指定的方法查出的结果
      column:指定将哪一列的值传给这个方法 
      流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
    -->
   <association property="dept" 
      select="com.kwy.mybatis.dao.DepartmentMapper.getDeptById"
      column="d_id">
   </association>
</resultMap>
<!--  public Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
   select * from tbl_employee where id=#{id}
   <if test="_parameter!=null">
      and 1=1
   </if>
</select>

分步查询好处:

1.组合已有的方法
2.可以使用延迟加载
   什么叫延迟加载: Employee==>Dept; Employee包含dept属性,我们每次查询Employee对象的时候,都将一起查询出来挺浪费资源的,所以可以改成部门信息在我们使用的时候再去查询
分段查询的基础上加上两个配置就可以实现延迟加载了

配置1.开启懒加载lazyLoadingEnabled, lazy loading开关,默认为true
配置2.aggressiveLazyLoading: 侵略性 lazy loading 开关, 默认为true, 这个属性,如果为true则当你访问任何一个属性都会加载所有的其他lazy load属性,即使你根本没有调用哪个lazy load属性,说白了就是aggressiveLazyLoading=true,则lazy load等于没用,所以要使用lazy load还是将其设为false

在mybatis-config.xml配置文件配置:

<settings>
   <!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题  -->
   <setting name="lazyLoadingEnabled" value="true"/>
   <setting name="aggressiveLazyLoading" value="false"/>
</settings>
场景二

查询部门的时候将部门对应的所有员工信息也查询出来

public class Department {
   
   private Integer id;
   private String departmentName;
   private List<Employee> emps;
   
   public List<Employee> getEmps() {
      return emps;
   }
   public void setEmps(List<Employee> emps) {
      this.emps = emps;
   }
......
}

 
 
<!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则  -->
<resultMap type="com.kwy.mybatis.bean.Department" id="MyDept">
   <id column="did" property="id"/>
   <result column="dept_name" property="departmentName"/>
   <!-- 
      collection定义关联集合类型的属性的封装规则 
      ofType:指定集合里面元素的类型
   -->
   <collection property="emps" ofType="com.kwy.mybatis.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>
<!-- public Department getDeptByIdPlus(Integer id); -->
<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 tbl_dept d
   LEFT JOIN tbl_employee e
   ON d.id=e.d_id
   WHERE d.id=#{id}
</select>

这个查询可不可以做成分布的

<!-- collection:分段查询 -->
<resultMap type="com.kwy.mybatis.bean.Department" id="MyDeptStep">
   <id column="id" property="id"/>
   <id column="dept_name" property="departmentName"/>
   <collection property="emps" 
      select="com.kwy.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
      column="{deptId=id}" fetchType="lazy"></collection>
</resultMap>
<!-- public Department getDeptByIdStep(Integer id); -->
<select id="getDeptByIdStep" resultMap="MyDeptStep">
   select id,dept_name from tbl_dept where id=#{id}
</select>

<!-- 扩展:多列的值传递过去:
      将多列的值封装map传递;
      column="{key1=column1,key2=column2}"
   fetchType="lazy":表示使用延迟加载;
         - lazy:延迟
         - eager:立即
 -->
再来说resultMap 另外一个属性: discriminator  mybatis可以根据鉴别器判断某列的值,然后根据某列的值来改变封装行为

这里就不举例说明了

下面来说一下mybatis注解

@Select("select * from tb1_employee where id=#{id}")
Employee selectByEmpId(String id);
这个就是最简单的使用方式了.我是感觉简单的使用注解还行,如果是复杂的,就不太好了. 而且这样总有一种java代码和sql又混在一起的感觉.


猜你喜欢

转载自blog.csdn.net/kwy15732621629/article/details/79769262