百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

MyBatis框架 - 映射文件(mybatis映射文件规则)

mhr18 2024-10-03 22:40 26 浏览 0 评论

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可以灵活的设置查询是否需要使用延迟加载,而不需要因为某个查询不想使用延迟加载将全局的延迟加载设置关闭.

相关推荐

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

备份软件调用rman接口备份报错RMAN-06820 ORA-17629 ORA-17627

一、报错描述:备份归档报错无法连接主库进行归档,监听问题12541RMAN-06820:WARNING:failedtoarchivecurrentlogatprimarydatab...

增量备份修复物理备库gap(增量备份恢复数据库步骤)

适用场景:主备不同步,主库归档日志已删除且无备份.解决方案:主库增量备份修复dg备库中的gap.具体步骤:1、停止同步>alterdatabaserecovermanagedstand...

一分钟看懂,如何白嫖sql工具(白嫖数据库)

如何白嫖sql工具?1分钟看懂。今天分享一个免费的sql工具,毕竟现在比较火的NavicatDbeaverDatagrip都需要付费才能使用完整功能。幸亏今天有了这款SQLynx,它不仅支持国内外...

「开源资讯」数据管理与可视化分析平台,DataGear 1.6.1 发布

前言数据齿轮(DataGear)是一款数据库管理系统,使用Java语言开发,采用浏览器/服务器架构,以数据管理为核心功能,支持多种数据库。它的数据模型并不是原始的数据库表,而是融合了数据库表及表间关系...

您还在手工打造增删改查代码么,该神器带你脱离苦海

作为Java开发程序,日常开发中,都会使用Spring框架,完成日常的功能开发;在相关业务系统中,难免存在各种增删改查的接口需求开发。通常来说,实现增删改查有如下几个方式:纯手工打造,编写各种Cont...

Linux基础知识(linux基础知识点及答案)

系统目录结构/bin:命令和应用程序。/boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。/dev:dev是Device(设备)的缩写,该目录...

PL/SQL 杂谈(二)(pl/sql developer使用)

承接(一)部分。我们从结构和功能这两个方面展示PL/SQL的关键要素。可以看看PL/SQL的优雅的代码。写出一个好的代码,就和文科生写出一篇优秀的作文一样,那么赏心悦目。1、与SQL的集成PL/S...

电商ERP系统哪个好用?(电商erp哪个好一点)

电商ERP系统哪个好用?做电商的,谁还没被ERP折腾过?有老板说:“我们早就上了ERP,订单、库存、财务全搞定,系统用得飞起。”也有运营吐槽:“系统是上了,可库存老不准,订单漏单错单天天有,财务对账还...

汽车检测线系统实例,看集中控制与PLC分布控制

PLC可编程控制器,上个世纪70年代初,为取代早期继电器控制线路,开始采取存储指令方式,完成顺序控制而设计的。开始仅有逻辑运算、计时、计数等简单功能。随着微处理的发展,PLC可编程能力日益提高,已经能...

苹果五件套成公司年会奖品主角,几大小技巧教你玩转苹果新品

钱江晚报·小时新闻记者张云山随着春节的临近,各家大公司的年会又将陆续上演。上周,各大游戏公司的年会大奖,苹果五件套又成了标配。在上海的游戏公司中,莉莉丝奖品列表拉得相当长,从特等奖到九等奖还包含了特...

取消回复欢迎 发表评论: