一、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 + '\'' + '}'; } }
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 + "]"; } }
数据库中创建响应的表
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}">