网站首页 > 技术文章 正文
4.1 Mybatis映射文件简介
1) MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
2) SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
cache – 给定命名空间的缓存配置。
cache-ref – 其他命名空间缓存配置的引用。
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。
sql – 可被其他语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语
4.2 Mybatis使用insert|update|delete|select完成CRUD
4.2.1 select
1) Mapper接口方法
public Employee getEmployeeById(Integer id ); |
2) Mapper映射文件
select id="getEmployeeById" resultType="com.learn.java.mybatis.beans.Employee"
databaseId="mysql">
select * from tbl_employee where id = ${_parameter}
</select>
4.2.2 insert
1) Mapper接口方法
public Integer insertEmployee(Employee employee); |
2) Mapper映射文件
<insert id="insertEmployee"
parameterType="com.java.learn.mybatis.beans.Employee"
databaseId="mysql">
insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>
4.2.3 update
1) Mapper接口方法
public Boolean updateEmployee(Employee employee); |
2) Mapper映射文件
<update id="updateEmployee" > update tbl_employee set last_name = #{lastName}, email = #{email}, gender = #{gender} where id = #{id} </update> |
4.2.4 delete
1) Mapper接口方法
public void deleteEmployeeById(Integer id ); |
2) Mapper映射文件
<delete id="deleteEmployeeById" > delete from tbl_employee where id = #{id} </delete> |
4.3 主键生成方式、获取主键值
4.3.1 主键生成方式
1) 支持主键自增,例如MySQL数据库
2) 不支持主键自增,例如Oracle数据库
需求: 插入一条新数据,立马查询这条数据.
4.3.2 获取主键值
1) 若数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),则可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上。
2) 而对于不支持自增型主键的数据库(例如 Oracle),则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用
<insert id="insertEmployee" parameterType="com.learn.java.mybatis.beans.Employee"
databaseId="mysql"
useGeneratedKeys="true"
keyProperty="id">
insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert><select id="getEmployeeById"
resultType="com.learn.java.mybatis.beans.Employee"
databaseId="mysql">
select * from tbl_employee where id = ${_parameter}
</select>
4.4 参数传递
4.4.1 参数传递的方式
1) 单个普通类型参数
可以接受基本类型,包装类型,字符串类型等。这种情况MyBatis可直接使用这个参数,不需要经过任何处理。
2) 多个参数
任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2...,或者0,1…,值就是参数的值
3) 命名参数
为参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中,key就是我们自己指定的名字
4) POJO
当这些参数属于我们业务POJO时,我们直接传递POJO
5) Map
我们也可以封装多个参数为map,直接传递
6) Collection/Array
会被MyBatis封装成一个map传入, Collection对应的key是collection,Array对应的key是array. 如果确定是List集合,key还可以是list.
4.4.2 参数传递源码分析
1) 以命名参数为例:
public Employee getEmployeeByIdAndLastName (@Param("id")Integer id, @Param("lastName")String lastName); |
2) 源码:
public Object getNamedParams(Object[] args) { final int paramCount = names.size(); if (args == null || paramCount == 0) { return null; } else if (!hasParamAnnotation && paramCount == 1) { return args[names.firstKey()]; } else { final Map<String, Object> param = new ParamMap<Object>(); int i = 0; for (Map.Entry<Integer, String> entry : names.entrySet()) { param.put(entry.getValue(), args[entry.getKey()]); // add generic param names (param1, param2, ...) final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1); // ensure not to overwrite parameter named with @Param if (!names.containsValue(genericParamName)) { param.put(genericParamName, args[entry.getKey()]); } i++; } return param; } } |
4.4.3 参数处理
1) 参数位置支持的属性:
javaType、jdbcType、mode、numericScale、resultMap、typeHandler、jdbcTypeName、expression
2) 实际上通常被设置的是:可能为空的列名指定 jdbcType ,例如:
insert into orcl_employee(id,last_name,email,gender) values(employee_seq.nextval,#{lastName,jdbcType=NULL },#{email},#{gender}) |
4.4.4 参数的获取方式
1) #{key}:获取参数的值,预编译到SQL中。安全。
2) ${key}:获取参数的值,拼接到SQL中。有SQL注入问题。
a) 使用此种方式获取参数时,不能任意书写参数,只能通过_parameter进行获取参数,eg:${_parameter}
b) 一般#{key}解决不了的问题,使用${key}获取参数
c) 底层原理使用Statement对象,不是占位符方式。
4.5 select查询的几种情况
1) 查询单行数据返回单个对象
public Employee getEmployeeById(Integer id ); |
2) 查询多行数据返回对象的集合
public List<Employee> getAllEmps(); |
3) 查询单行数据返回Map集合
public Map<String,Object> getEmployeeByIdReturnMap(Integer id ); |
4) 查询多行数据返回Map集合
@MapKey("id") // 指定使用对象的哪个属性来充当map的key public Map<Integer,Employee> getAllEmpsReturnMap(); |
4.6 resultType自动映射
1) autoMappingBehavior默认是PARTIAL,开启自动映射的功能。唯一的要求是结果集列名和javaBean属性名一致
2) 如果autoMappingBehavior设置为NONE则会取消自动映射
3) 数据库字段命名规范,POJO属性符合驼峰命名法,如A_COLUMN?aColumn,我们可以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true
4.7 resultMap自定义映射
1) 自定义resultMap,实现高级结果集映射
2) id :用于完成主键值的映射
3) result :用于完成普通列的映射
4) association :一个复杂的类型关联;许多结果将包装成这种类型
5) collection : 复杂类型的集
4.7.1 id&result
<select id="getEmployeeById" resultMap="myEmp">
select id, last_name,email, gender from tbl_employee where id =#{id}
</select>
<resultMap type="com.learn.java.mybatis.beans.Employee" id="myEmp">
<id column="id" property="id" />
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</resultMap>
4.7.2 association
1) POJO中的属性可能会是一个对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用association标签定义对象的封装规则
public class Department { private Integer id ; private String deptName ; // 省略 get/set方法 } |
public class Employee { private Integer id ; private String lastName; private String email ; private String gender ; private Department dept ; // 省略 get/set方法 } |
表结构准备
CREATE TABLE tbl_dept(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(50) NOT NULL
);
ALTER TABLE tbl_employee ADD COLUMN dept_id INT(11);
ALTER TABLE tbl_employee ADD CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id) REFERENCES tbl_dept(id);
2) 使用级联的方式:
<select id="getEmployeeAndDept" resultMap="myEmpAndDept" >
SELECT e.id eid, e.last_name, e.email,e.gender ,d.id did, d.dept_name FROM tbl_employee e , tbl_dept d WHERE e.d_id = d.id AND e.id = #{id}
</select>
<resultMap type="com.learn.java.mybatis.beans.Employee" id="myEmpAndDept">
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<!-- 级联的方式 -->
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
</resultMap>
3) Association‘
<resultMap type="com.java.learn.mybatis.beans.Employee" id="myEmpAndDept">
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<association property="dept" javaType="com.learn.java.mybatis.beans.Department">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
</association>
</resultMap>
4.7.3 association 分步查询
1) 实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层, 因此
对于查询员工信息并且将对应的部门信息也查询出来的需求,就可以通过分步的方式
完成查询。
① 先通过员工的id查询员工信息
② 再通过查询出来的员工信息中的外键(部门id)查询对应的部门信息.
<select id="getEmployeeAndDeptStep" resultMap="myEmpAndDeptStep">
select id, last_name, email,gender,d_id from tbl_employee where id =#{id}
</select>
<resultMap type="com.learn.java.mybatis.beans.Employee" id="myEmpAndDeptStep">
<id column="id" property="id" />
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<association property="dept" select="com.java.learn.mybatis.dao.DepartmentMapper.getDeptById"
column="d_id" fetchType="eager">
</association>
</resultMap>
4.7.4 association 分步查询使用延迟加载(懒加载)
1) 在分步查询的基础上,可以使用延迟加载来提升查询的效率,只需要在全局的
Settings中进行如下的配置:
<!-- 开启延迟加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 设置加载的数据是按需还是全部 --> <setting name="aggressiveLazyLoading" value="false"/> |
4.7.5 collection
1) POJO中的属性可能会是一个集合对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用collection标签定义对象的封装规则
public class Department { private Integer id ; private String departmentName ; private List<Employee> emps ; } |
2) Collection
<select id="getDeptAndEmpsById" resultMap="myDeptAndEmps">
SELECT d.id did, d.dept_name ,e.id eid ,e.last_name ,e.email,e.gender
FROM tbl_dept d LEFT OUTER JOIN tbl_employee e ON d.id = e.d_id
WHERE d.id = #{id}
</select>
<resultMap type="com.java.learn.mybatis.beans.Department" id="myDeptAndEmps">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
<!--
property: 关联的属性名
ofType: 集合中元素的类型
-->
<collection property="emps" ofType="com.java.learn.mybatis.beans.Employee">
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</collection>
</resultMap>
4.7.6 collection 分步查询
1) 实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层, 因此
对于查询部门信息并且将对应的所有的员工信息也查询出来的需求,就可以通过分步的方式完成查询。
③ 先通过部门的id查询部门信息
④ 再通过部门id作为员工的外键查询对应的部门信息.
<select id="getDeptAndEmpsByIdStep" resultMap="myDeptAndEmpsStep">
select id ,dept_name from tbl_dept where id = #{id}
</select>
<resultMap type="com.java.learn.mybatis.beans.Department" id="myDeptAndEmpsStep">
<id column="id" property="id"/>
<result column="dept_name" property="departmentName"/>
<collection property="emps"
select="com.java.learn.mybatis.dao.EmployeeMapper.getEmpsByDid"
column="id">
</collection>
</resultMap>
4.7.7 collection 分步查询使用延迟加载
4.7.8 扩展: 分步查询多列值的传递
1) 如果分步查询时,需要传递给调用的查询中多个参数,则需要将多个参数封装成
Map来进行传递,语法如下: {k1=v1, k2=v2....}
2) 在所调用的查询方,取值时就要参考Map的取值方式,需要严格的按照封装map
时所用的key来取值.
4.7.9 扩展: association 或 collection的 fetchType属性
1) 在<association> 和<collection>标签中都可以设置fetchType,指定本次查询是否要使用延迟加载。默认为 fetchType=”lazy” ,如果本次的查询不想使用延迟加载,则可设置为
fetchType=”eager”.
2) fetchType可以灵活的设置查询是否需要使用延迟加载,而不需要因为某个查询不想使用延迟加载将全局的延迟加载设置关闭.
- 上一篇: 数据库操作语言SQL数据处理的增、查、删、改
- 下一篇: mybatis插入获取主键的方式和原理
猜你喜欢
- 2024-10-27 一文看懂mycat配置--数据库的读写分离、分表分库
- 2024-10-27 基于Percona XtraBackup 实现全备&增量备份与恢复
- 2024-10-27 Java EE核心框架实战:如何使用MyBatis实现CURD-2种数据库
- 2024-10-27 mysql如何进行累加计算 mysql 变量累加
- 2024-10-27 Springboot集成Mybatis ID生成策略注解 @GeneratedValue
- 2024-10-27 mybatis插入获取主键的方式和原理
- 2024-10-27 mybatis-plus保姆级入门教程,手把手教你轻松实现增删改查
- 2024-10-27 数据库操作语言SQL数据处理的增、查、删、改
- 2024-10-27 终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了
- 2024-10-27 一文带你搞定mybatis的映射配置文件
你 发表评论:
欢迎- 633℃几个Oracle空值处理函数 oracle处理null值的函数
- 626℃Oracle分析函数之Lag和Lead()使用
- 614℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 608℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 606℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 599℃【数据统计分析】详解Oracle分组函数之CUBE
- 588℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 573℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
-
- oracle 19cOCM认证有哪些内容(oracle认证ocm月薪)
- Oracle新出AI课程认证,转型要持续学习
- oracle 表的查询join顺序,可能会影响查询效率
- Oracle DatabaseAmazon Web Services正式可用,Oracle数据库上云更容易了
- Oracle 19.28 RU 升级最佳实践指南
- 汉得信息:发布EBS系统安装启用JWS的高效解决方案
- 如何主导设计一个亿级高并发系统架构-数据存储架构(三)
- Java 后端开发必看!工厂设计模式轻松拿捏
- ORA-00600 「25027」 「x」报错(抱错孩子电视剧 爸爸是武术 另一个爸爸是画家)
- 新项目终于用上了jdk24(jdk新建项目)
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端获取当前时间 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (58)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)