标签:查询语句 sele UNC 代码生成 加载 oci nic mamicode 可扩展
传统的JDBC编程存在的弊端:
ü 工作量大,操作数据库至少要5步;
ü 业务代码和技术代码耦合;
ü 连接资源手动关闭,带来了隐患;
MyBatis前身是iBatis,其源于“Internet”和“ibatis”的组合,本质是一种半自动的ORM框架,除了POJO和映射关系之外,还需要编写SQL语句;Mybatis映射文件三要素:SQL、映射规则和POJO;
步骤如下:
核心类分析:
resultType:当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。
自动映射注意事项 :
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,在对复杂语句进行联合映射的时候,它很可能可以代替数千行的同等功能的代码。 ResultMap 的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。
属性 |
描述 |
id |
当前命名空间中的一个唯一标识,用于标识一个result map. |
type |
类的完全限定名, 或者一个类型别名. |
autoMapping |
如果设置这个属性,MyBatis将会为这个ResultMap开启或者关闭自动映射。这个属性会覆盖全局的属性 autoMappingBehavior。默认值为:unset。 |
使用场景总结:1. 字段有自定义的转化规则;2. 复杂的多表查询
强制使用resultMap, 不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义;见《Java开发手册1.5》之5.4.3;
传递参数有三种方式:
方式 |
描述 |
使用map传递参数 |
可读性差,导致可维护性和可扩展性差,杜绝使用 |
使用注解传递参数 |
直观明了,当参数较少一般小于5个的时候,建议使用 |
使用Java Bean的方式传递参数 |
当参数大于5个的时候,建议使用 |
建议不要用Map作为mapper的输入和输出,不利于代码的可读性和可维护性;见《Java开发手册1.5》之5.4.6;
属性 |
描述 |
useGeneratedKeys |
(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 |
keyProperty |
(仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
注意:自增长序号不是简单的行数+1,而是序号最大值+1;
属性 |
描述 |
keyProperty |
selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
resultType |
结果的类型。MyBatis 通常可以推算出来,但是为了更加确定写上也不会有什么问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的 Object 或一个 Map。 |
order |
这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后获取主键字段;mysql数据库自增长的方式order设置为After,oracle数据库通过sequnce获取主键order设置为Before |
Oracle通过sequnce获取主键示例:
<selectKey keyProperty=“id” order= " Before" resultType="int">
select SEQ_ID.nextval from dual
</selectKey>
Mysql通过自增长序号获取主键示例:
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
5. SQL元素和SQL的参数
SQL元素:用来定义可重用的 SQL 代码段,可以包含在其他语句中;
SQL参数:向sql语句中传递的可变参数,分为预编译#{}和传值${}两种
ü 预编译 #{}:将传入的数据都当成一个字符串,会对自动传入的数据加一个单引号,能够很大程度防止sql注入;
ü 传值${}:传入的数据直接显示生成在sql中,无法防止sql注入;适用场景:动态报表,表名、选取的列是动态的,order by和in操作, 可以考虑使用$
示例代码:com.enjoylearning.mybatis.MybatisDemo.testSymbol
建议:sql.xml 配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL 注入。见《Java开发手册1.5》之5.4.4;
元素 |
作用 |
备注 |
if |
判断语句 |
单条件分支判断 |
choose、when、otherwise |
相当于java的case when |
多条件分支判断 |
Trim、where、set |
辅助元素 |
用于处理sql拼装问题 |
foreach |
循环语句 |
在in语句等列举条件常用,常用于实现批量操作 |
|
MyBatis Generator:MyBatis 的开发团队提供了一个很强大的代码生成器,代码包含了数据库表对应的实体类 、Mapper 接口类、 Mapper XML 文件等,这些代码文件中几乎包含了全部的单表操作方法,使用 MBG 可以极大程度上方便我们使用 MyBatis,还可以减少很多重复操作;MyBatis Generator的核心就是配置文件,完整的配置文件见:
运行MGB的方式有三种,见下表:
方式 |
运行代码 |
推荐使用场景 |
作为 Maven Plugin运行 |
mvn mybatis-generator:generate |
对逆向工程定制较多,项目工程结构比较单一的情况 |
运行Java 程序使用 XML配置文件 |
com.enjoylearning.mybatis.MybatisDemo.mybatisGeneratorTest |
|
从命令提示符 使用 XML 配置文件 |
java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml 具体见网盘:逆向工程 |
对逆向工程定制较少,项目工程结构比较复杂的情况 |
关联元素:association用于表示一对一关系,collection用于表示一对多关系;
关联方式:
ü 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
ü 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型
association标签 嵌套结果方式 常用属性:
ü property :对应实体类中的属性名,必填项。
ü javaType :属性对应的 Java 类型 。
ü resultMap :可以直接使用现有的 resultMap ,而不需要在这里配置映射关系。
ü columnPrefix :查询列的前缀,配置前缀后,在子标签配置 result 的 column 时可以省略前缀
示例代码:com.enjoylearning.mybatis.testOneToOne.
开发小技巧:
association标签 嵌套查询方式 常用属性:
ü select :另 一个映射查询的 id, MyBatis 会额外执行这个查询获取嵌套对象的结果 。
ü column :列名(或别名),将主查询中列的结果作为嵌套查询的参数。
ü fetchType :数据加载方式,可选值为 lazy 和 eager,分别为延迟加载和积极加载 ,这个配置会覆盖全局的 lazyLoadingEnabled 配置;
示例代码:com.enjoylearning.mybatis.testOneToOne().
嵌套查询会导致“N+1 查询问题”,导致该问题产生的原因:
这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。
解决“N+1 查询问题”的办法就是开启懒加载、按需加载数据,开启懒加载配置:
在<select>节点上配置“fetchType=lazy”
在MyBatis核心配置文件中加入如下配置:
<!-- 开启懒加载 ,当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true -->
<setting name="aggressiveLazyLoading" value="false" />
collection 支持的属性以及属性的作用和 association 完全相同。mybatis会根据id标签,进行字段的合并,合理配置好ID标签可以提高处理的效率;
开发小技巧:如果要配置一个相当复杂的映射,一定要从基础映射开始配置,每增加一些配置就进行对应的测试,在循序渐进的过程中更容易发现和解决问题 。
要实现多对多的关联,需要满足如下两个条件:
MyBatis 包含一个非常强大的查询缓存特性,使用缓存可以使应用更快地获取数据,避免频繁的数据库交互 ;
一级缓存默认会启用,想要关闭一级缓存可以在select标签上配置flushCache=“true”;一级缓存存在于 SqlSession 的生命周期中,在同一个 SqlSession 中查询时, MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中己经存在该键值时,则会返回缓存中的对象;任何的 INSERT 、UPDATE 、 DELETE 操作都会清空一级缓存;
二级缓存也叫应用缓存,存在于 SqlSessionFactory 的生命周期中,可以理解为跨sqlSession;缓存是以namespace为单位的,不同namespace下的操作互不影响。在MyBatis的核心配置文件中 cacheEnabled参数是二级缓存的全局开关,默认值是 true,如果把这个参数设置为 false,即使有后面的二级缓存配置,也不会生效;
要开启二级缓存,你需要在你的 SQL Mapper文件中添加配置:
<cache eviction=“LRU" flushInterval="60000" size="512" readOnly="true"/>
这段配置的效果如下:
ü 映射语句文件中的所有 select 语句将会被缓存。
ü 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
ü 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
ü 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
ü 缓存会存储列表集合或对象(无论查询方法返回什么)的 512个引用。
ü 缓存会被视为是 read/write(可读/可写)的缓存;
开发建议:使用二级缓存容易出现脏读,建议避免使用二级缓存,在业务层使用可控制的缓存代替更好;
缓存的调用过程如下:
调用过程解读:
标签:查询语句 sele UNC 代码生成 加载 oci nic mamicode 可扩展
原文地址:https://www.cnblogs.com/Soy-technology/p/11415751.html