Mybatis_映射文件_Select

本文详细介绍了MyBatis中各种复杂查询的实现方法,包括单表查询返回List和Map、多表联合查询、关联对象及集合类型的数据封装,以及如何通过配置实现延迟加载等功能。

一、Select元素来定义查询操作

  • Id:唯一标识符。用来引用这条SQL语句,需要和接口的方法名一致
  • parameterType:参数类型。可以不传,MyBatis会根据TypeHandler自动推断
  • resultType:返回值类型。别名或者全类名,如果返回的是集合,定义集合中元素的类型。不能和resultMap同时使用

Employee对象

package com.nuch.edu.domain;

/**
 * Created by yangshijing on 2017/12/4 0004.
 */
public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private String gender;
    private Department dept;

    public Employee() {
    }

    public Employee(String email, String gender, Integer id, String lastName) {
        this.email = email;
        this.gender = gender;
        this.id = id;
        this.lastName = lastName;
    }

    public Department getDept() {
        return dept;
    }

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

    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;
    }

    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;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "dept=" + dept +
                ", id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}
View Code

Department对象

package com.nuch.edu.domain;

import java.util.List;

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
                + "]";
    }
}
View Code

数据库中创建响应的表

DROP TABLE IF EXISTS `tbl_employee`;
CREATE TABLE `tbl_employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `last_name` varchar(255) DEFAULT NULL,
  `gender` char(1) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `dept_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `tbl_dept`;
CREATE TABLE `tbl_dept` (
  `id` int(11) NOT NULL,
  `dept_name` varchar(25) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

二、查询返回List结果集

resultType要指定集合中元素的类型

①.mapper接口

package com.nuch.edu.mapper;
import com.nuch.edu.domain.Employee;import java.util.List;/**
 * Created by yangshijing on 2017/12/4 0004.
 */
public interface EmployeeMapper {public List<Employee> getEmpReturnList(String lastName);

}

②.映射文件

<select id="getEmpReturnList" resultType="com.nuch.edu.domain.Employee">
         SELECT * FROM tbl_employee
           WHERE last_name like #{lastName}
</select>

③.测试代码

package com.nuch.edu;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.nuch.edu.domain.Employee;
import com.nuch.edu.mapper.EmployeeMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

/**
 * Created by yangshijing on 2017/12/4 0004.
 */
public class MybatisTest {
    @Test
    public void test1() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession sqlSession = sqlSessionFactory.openSession();

        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
      
       try {
           //测试添加
           //Employee employee = new Employee("tom@nchu.com", "0", null, "tom");
           //mapper.addEmp(employee);
           //System.out.print(employee.getId());

           //测试删除
           //mapper.deleteEmp(2);

           //测试更改
           //Employee employee = new Employee("jerry@nchu.com","0",3,"jerry");
           //mapper.updateEmp(employee);

           //测试参数
           //Employee jerry = mapper.getEmpByIdAndLastName(3, "jerry");

           //测试Map
          /*Map<String,Object> map = new HashMap<>();
           map.put("id",3);
           map.put("lastName","jerry");
           Employee jerry = mapper.getEmpByMap(map);
           System.out.print(jerry);*/

           //测试返回map类型
          /* Map<String, Object> map = mapper.getEmpReturnMap("jerry");
           System.out.print(map);*/

           //测试返回List
           List<Employee> list = mapper.getEmpReturnList("%t%");
           System.out.print(list);

           //测试返回多条map记录
           /*Map<String,Employee> map = mapper.getEmpReturnMap1("%t%");
           System.out.print(map);*/
       
           sqlSession.commit();
       }finally {
           sqlSession.close();
       }
    }
}

④.测试结果

DEBUG 12-19 13:47:37,089 ==>  Preparing: SELECT * FROM tbl_employee WHERE last_name like ?   (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:47:37,133 ==> Parameters: %t%(String)  (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:47:37,174 <==      Total: 2  (BaseJdbcLogger.java:145) 
[Employee{dept=null, id=1, lastName='null', email='tom@qq.com', gender='1'}, Employee{dept=null, id=4, lastName='null', email='tom@nchu.com', gender='0'}]

三、返回Map结果集

返回一条记录的map;key就是列名,值就是对应的值;resultType指定为map

<select id="getEmpReturnMap" resultType="map">
        SELECT * FROM tbl_employee
           WHERE last_name = #{lastName}
</select>
 public Map<String,Object> getEmpReturnMap(String lastName);
Map<String, Object> map = mapper.getEmpReturnMap("jerry");
DEBUG 12-19 13:50:59,755 ==>  Preparing: SELECT * FROM tbl_employee WHERE last_name = ?   (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:50:59,809 ==> Parameters: jerry(String)  (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:50:59,939 <==      Total: 1  (BaseJdbcLogger.java:145) 
{gender=0, last_name=jerry, id=3, dept_id=1, email=jerry@nchu.com}

多条记录封装为一个map,在mapper接口中的方法上加@MapKey注解;resultType指定为map中元素的类型

  • key:@Mapkey声明的属性
  • value:Employee对象
 /**
     * 返回多条记录
     * @param lastName
     * @return
     */
    @MapKey("lastName")
    public Map<String,Employee> getEmpReturnMap1(String lastName);
 <select id="getEmpReturnMap1" resultType="com.nuch.edu.domain.Employee">
        SELECT * FROM tbl_employee
           WHERE last_name like #{lastName}
 </select>
//测试返回多条map记录
 Map<String,Employee> map = mapper.getEmpReturnMap1("%t%");
DEBUG 12-19 13:57:39,151 ==>  Preparing: SELECT * FROM tbl_employee WHERE last_name like ?   (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:57:39,215 ==> Parameters: %t%(String)  (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:57:39,272 <==      Total: 2  (BaseJdbcLogger.java:145) 
{Tom=Employee{dept=null, id=1, lastName='Tom', email='tom@qq.com', gender='1'}, tom=Employee{dept=null, id=4, lastName='tom', email='tom@nchu.com', gender='0'}}

四、自动映射

1、全局setting设置

  • autoMappingBehavior默认是PARTIAL,开启自动映射的功能。唯一的要求是列名和javaBean属性名一致
  • 如果autoMappingBehavior设置为null则会取消自动映射数据库字段命名规范。POJO属性符合驼峰命名法,如A_COLUMN->aColumn,我们可以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true。

2、自定义resultMap,实现高级结果集映射

  • id – 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能
  • result – 注入到字段或 JavaBean 属性的普通结果
<!--resultMap:自定义结果集映射规则
    type:类的全限定名, 或者一个类型别名
    id:当前命名空间中的一个唯一标识,用于标识一个result map.
-->
<resultMap id="myResultMap" type="com.nuch.edu.domain.Employee">
<!--id 和 result 都映射一个单独列的值到简单数据类型的单独属性或字段。
  column:从数据库中得到的列名,或者是列名的重命名标签。
  property:映射到列结果的字段或属性。
-->
        <id column="id" property="id"></id>
        <!-- 定义普通列封装规则 -->
        <result column="last_name" property="lastName"></result>
        <!-- 其他不指定的列会自动封装-->
</resultMap>
   
<select id="getEmployeeByid" resultMap="myResultMap">
        select id,last_name,email,gender  from tbl_employee where id = #{id}
</select>

五、多表联合查询

当一个Javabean有对另一个对象的引用时,使用传统的resultType无法实现对引用的封装,这时要用到reslultMap

①.级联属性封装结果集

  /**
     * 多表联合查询
     */
    public Employee getEmpAndDep(Integer id);  
  <!--
   联合查询:级联属性封装结果集
  -->
  <resultMap id="test1" type="com.nuch.edu.domain.Employee">
        <id column="id" property="id"></id>
        <result column="last_name" property="lastName"></result>
        <result column="gender" property="gender"></result>
        <result column="email" property="email"></result>
        <result column="did" property="dept.id"></result>
        <result column="dept_name" property="dept.departmentName"></result>
    </resultMap>

    <select id="getEmpAndDep" resultMap="test1">
        SELECT d.id did ,d.dept_name dept_name ,
        e.id id, e.last_name last_name,e.gender gender, e.email email
        from tbl_dept d ,tbl_employee e
        WHERE     d.id = e.dept_id
        and e.id = 1
    </select>
  //测试多表查询
Employee empAndDep = mapper.getEmpAndDep(1);
System.out.print(empAndDep);
DEBUG 12-19 13:59:14,637 ==>  Preparing: SELECT d.id did ,d.dept_name dept_name , e.id id, e.last_name last_name,e.gender gender, e.email email from tbl_dept d ,tbl_employee e WHERE d.id = e.dept_id and e.id = 1   (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:59:14,682 ==> Parameters:   (BaseJdbcLogger.java:145) 
DEBUG 12-19 13:59:14,731 <==      Total: 1  (BaseJdbcLogger.java:145) 
Employee{dept=Department [id=1, departmentName=开发部], id=1, lastName='Tom', email='tom@qq.com', gender='1'}
②.association嵌套结果集
  <!--
       使用association定义关联对象的封装规则;
    -->
    <resultMap id="test2" type="com.nuch.edu.domain.Employee">
        <id column="id" property="id"></id>
        <result column="last_name" property="lastName"></result>
        <result column="gender" property="gender"></result>
        <result column="email" property="email"></result>
        <!--  association可以指定联合的javaBean对象
        property="dept":指定哪个属性是联合的对象
        javaType:指定这个属性对象的类型[不能省略]
        -->
       <association property="dept" javaType="com.nuch.edu.domain.Department">
      <!--column:数据库查询结果的列名
        property:联合对象的属性名
      --> <id column="did" property="id"></id> <result column="dept_name" property="departmentName"></result> </association> </resultMap> <select id="getEmpAndDep" resultMap="test2"> SELECT d.id did ,d.dept_name dept_name , e.id id, e.last_name last_name,e.gender gender, e.email email from tbl_dept d ,tbl_employee e WHERE d.id = e.dept_id and e.id = 1 </select>

③.association分步查询

1.添加DepartmentMapper接口

package com.nuch.edu.mapper;

import com.nuch.edu.domain.Department;

/**
 * Created by yangshijing on 2017/12/19 0019.
 */
public interface  DepartmentMapper {
    public Department getDepById(Integer id);
}

2.添加DepartmentMapper.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.nuch.edu.mapper.DepartmentMapper">
    <select id="getDepById" resultType="com.nuch.edu.domain.Department">
        SELECT id ,dept_name departmentName FROM  tbl_dept WHERE id = #{id}
    </select>
</mapper>

3.类路径下的mybaits-config.xml引入映射文件

 <mappers>
        <mapper resource="EmployeeMapper.xml"/>
        <mapper resource="DepartmentMapper.xml"/>
 </mappers>

4.EmployeeMapper接口添加方法

  public  Employee getEmpByStep(Integer id);

5.EmployeeMapper.xml添加映射

 <!-- 使用association进行分步查询:
            1、先按照员工id查询员工信息
            2、根据查询员工信息中的dept_id值去部门表查出部门信息
            3、部门信息封装到员工属性中;
  -->
    <resultMap id="test3" type="com.nuch.edu.domain.Employee">
        <id column="id" property="id"></id>
        <result column="last_name" property="lastName"></result>
        <result column="gender" property="gender"></result>
        <result column="email" property="email"></result>
        <!-- association定义关联对象的封装规则
             select:调用目标的方法查询当前属性的值
             column:将指定列的值传入目标方法

             流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
          -->
        <association property="dept" select="com.nuch.edu.mapper.DepartmentMapper.getDepById"
        column="dept_id">
        </association>
    </resultMap>

    <select id="getEmpByStep" resultMap="test3">
        SELECT * FROM tbl_employee WHERE id=#{id}
    </select>

6.测试代码

          //测试分步查询
           /*Department depById = deptMapper.getDepById(1);
           System.out.print(depById);*/
           Employee empByStep = mapper.getEmpByStep(1);
           System.out.print(empByStep);    

7.结果

DEBUG 12-19 14:44:04,928 ==>  Preparing: SELECT * FROM tbl_employee WHERE id=?  
DEBUG 12-19 14:44:05,102 ==> Parameters: 1(Integer) 
DEBUG 12-19 14:44:05,130 ====>  Preparing: SELECT id ,dept_name departmentName FROM tbl_dept WHERE id = ? 
DEBUG 12-19 14:44:05,131 ====> Parameters: 1(Integer)  
DEBUG 12-19 14:44:05,145 <====      Total: 1 
DEBUG 12-19 14:44:05,146 <==      Total: 1  
Employee{dept=Department [id=1, departmentName=开发部], id=1, lastName='Tom', email='tom@qq.com', gender='1'}

六、assocation延时加载

1.开启延迟加载和属性按需加载;分步查询的基础之上加上两个配置:

<!-- 可以使用延迟加载(懒加载);(按需加载)
Employee==>Dept:
我们每次查询Employee对象的时候,都将一起查询出来。
部门信息在我们使用的时候再去查询;
-->
<settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--  开启延时加载-->
        <setting name="lazyLoadingEnabled" value="true"></setting>
        <setting name="aggressiveLazyLoading" value="false"></setting>
 </settings>

2.测试代码

Employee empByStep = mapper.getEmpByStep(1);
System.out.println(empByStep.getLastName());
System.out.println(empByStep.getDept());

3.结果

DEBUG 12-19 15:00:42,602 ==>  Preparing: SELECT * FROM tbl_employee WHERE id=? 
DEBUG 12-19 15:00:42,666 ==> Parameters: 1(Integer) 
DEBUG 12-19 15:00:42,824 <==      Total: 1
Tom
DEBUG 12-19 15:00:42,825 ==>  Preparing: SELECT id ,dept_name departmentName FROM tbl_dept WHERE id = ? 
DEBUG 12-19 15:00:42,827 ==> Parameters: 1(Integer) 
DEBUG 12-19 15:00:42,830 <==      Total: 1  
Department [id=1, departmentName=开发部]

七、Collection-集合类型&嵌套结果集

1.Department对象添加List<Employee>类型的属性

  private List<Employee> emps;

    public List<Employee> getEmps() {
        return emps;
    }
    public void setEmps(List<Employee> emps) {
        this.emps = emps;
    }

2.DepartmentMapper接口添加方法

package com.nuch.edu.mapper;

import com.nuch.edu.domain.Department;

/**
 * Created by yangshijing on 2017/12/19 0019.
 */
public interface  DepartmentMapper {
  public Department getDepCollection(Integer id);
}

3.DepartmentMapper.xml添加映射

<resultMap id="test1" type="com.nuch.edu.domain.Department">
        <id column="did" property="id"></id>
        <result column="dept_name" property="departmentName"></result>
        <!--
            collection定义关联集合类型的属性的封装规则
            ofType:指定集合里面元素的类型
        -->
        <collection property="emps" ofType="com.nuch.edu.domain.Employee">
            <!-- 定义这个集合中元素的封装规则 -->
            <id column="eid" property="id"></id>
            <result column="gender" property="gender"></result>
            <result column="last_name" property="lastName"></result>
            <result column="email" property="email"></result>
        </collection>
    </resultMap>
    <select id="getDepCollection" resultMap="test1">
        SELECT d.id did,d.dept_name dept_name,
                e.id eid,e.gender gender,e.last_name last_name ,e.email email
            FROM tbl_dept d LEFT JOIN tbl_employee e
            on  d.id = e.dept_id
            WHERE d.id = #{id};
    </select>

4.测试代码

   //测试集合属性
    Department depCollection = deptMapper.getDepCollection(1);
    System.out.println(depCollection);
    System.out.println(depCollection.getEmps());

5.结果

DEBUG 12-19 15:30:18,003 ==>  Preparing: SELECT d.id did,d.dept_name dept_name, e.id eid,e.gender gender,e.last_name last_name ,e.email email FROM tbl_dept d LEFT JOIN tbl_employee e on d.id = e.dept_id WHERE d.id = ?; 

DEBUG 12-19 15:30:18,090 ==> Parameters: 1(Integer) DEBUG 12-19 15:30:18,127 <== Total: 2 Department [id=1, departmentName=开发部] [Employee{id=1, lastName='Tom', email='tom@qq.com', gender='1'}, Employee{id=3, lastName='jerry', email='jerry@nchu.com', gender='0'}]

八、Collection-分步查询&延迟加载

1.DepartmentMapper接口添加方法

package com.nuch.edu.mapper;
import com.nuch.edu.domain.Department;
/**
 * Created by yangshijing on 2017/12/19 0019.
 */
public interface  DepartmentMapper {
    public Department getDepByStep(Integer id);
}

2.DepartmentMapper.xml添加映射

  <resultMap id="test2" type="com.nuch.edu.domain.Department">
      <id column="id" property="id"></id>
      <result column="dept_name" property="departmentName"></result>
      <collection property="emps"  ofType="com.nuch.edu.domain.Employee"
     select="com.nuch.edu.mapper.EmployeeMapper.getEmpByDepId" column="id">    </collection> </resultMap> <select id="getDepByStep" resultMap="test2"> SELECT * FROM tbl_dept WHERE id=#{id} </select>

3.测试代码

Department depByStep = deptMapper.getDepByStep(1);
System.out.println(depByStep);
System.out.print(depByStep.getEmps());

4.结果

DEBUG 12-19 15:59:22,756 ==>  Preparing: SELECT * FROM tbl_dept WHERE id=?
DEBUG 12-19 15:59:22,819 ==> Parameters: 1(Integer) 
DEBUG 12-19 15:59:23,020 <==      Total: 1  
DEBUG 12-19 15:59:23,022 ==>  Preparing: SELECT * FROM tbl_employee WHERE dept_id = ?  
DEBUG 12-19 15:59:23,023 ==> Parameters: 1(Integer)
DEBUG 12-19 15:59:23,028 <==      Total: 2 
Department [id=1, departmentName=开发部]
[Employee{id=1, lastName='Tom', email='tom@qq.com', gender='1'}, Employee{id=3, lastName='jerry', email='jerry@nchu.com', gender='0'}]

5.fetchType="lazy":表示使用延迟加载

- lazy:延迟
- eager:立即

association或者collection标签的 fetchType=eager/lazy可以覆盖全局的延迟加载策略, 指定立即加载(eager)或者延迟加载(lazy)

 <collection property="emps"   fetchType="lazy" select="com.nuch.edu.mapper.EmployeeMapper.getEmpByDepId" column="id">
</collection>

6.将多列的值封装map传递

<!--column="{key1=column1,key2=column2}-->
<!--key:select目标sql#{}中的名字-->   
<collection property="emps"   fetchType="lazy" select="com.nuch.edu.mapper.EmployeeMapper.getEmpByDepId" column="{dept_id=id}">

转载于:https://www.cnblogs.com/realshijing/p/8059405.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值