导图社区 Mybatis
Java开发中常用SSM(Spring,SpringMVC,Mybatis)组合中的Mybatis框架的使用要点
编辑于2019-04-28 03:28:13Mybatis
参数处理
单个参数:mybatis不会做特殊处理, #{参数名/任意名}:取出参数值。 多个参数:mybatis会做特殊处理。 多个参数会被封装成 一个map, key:param1...paramN,或者参数的索引也可以 value:传入的参数值 #{}就是从map中获取指定的key的值; 异常:(错误操作产生的异常) org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [1, 0, param1, param2] 操作:(错误操作) 方法:public Employee getEmpByIdAndLastName(Integer id,String lastName); 取值:#{id},#{lastName} 【命名参数】:明确指定封装参数时map的key;@Param("id") 多个参数会被封装成 一个map, key:使用@Param注解指定的值 value:参数值 #{指定的key}取出对应的参数值 POJO: 如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo; #{属性名}:取出传入的pojo的属性值 Map: 如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map #{key}:取出map中对应的值 TO: 如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO(Transfer Object)数据传输对象 Page{ int index; int size; } ========================思考================================ public Employee getEmp(@Param("id")Integer id,String lastName); 取值:id==>#{id/param1} lastName==>#{param2} public Employee getEmp(Integer id,@Param("e")Employee emp); 取值:id==>#{param1} lastName===>#{param2.lastName/e.lastName} ##特别注意:如果是Collection(List、Set)类型或者是数组, 也会特殊处理。也是把传入的list或者数组封装在map中。 key:Collection(collection),如果是List还可以使用这个key(list) 数组(array) public Employee getEmpById(List<Integer> ids); 取值:取出第一个id的值: #{list[0]} ========================结合源码,mybatis怎么处理参数========================== 总结:参数多时会封装map,为了不混乱,我们可以使用@Param来指定封装时使用的key; #{key}就可以取出map中的值; (@Param("id")Integer id,@Param("lastName")String lastName); ParamNameResolver解析参数封装map的; //1、names:{0=id, 1=lastName};构造器的时候就确定好了 确定流程: 1.获取每个标了param注解的参数的@Param的值:id,lastName; 赋值给name; 2.每次解析一个参数给map中保存信息:(key:参数索引,value:name的值) name的值: 标注了param注解:注解的值 没有标注: 1.全局配置:useActualParamName(jdk1.8)(这个属性需要在全局配置文件的setting中设置)):name=参数名 2.name=map.size();相当于当前元素的索引 {0=id, 1=lastName,2=2} args【1,"Tom",'hello'】: public Object getNamedParams(Object[] args) { final int paramCount = names.size(); //1、参数为null直接返回 if (args == null || paramCount == 0) { return null; //2、如果只有一个元素,并且没有Param注解;args[0]:单个参数直接返回 } else if (!hasParamAnnotation && paramCount == 1) { return args[names.firstKey()]; //3、多个元素或者有Param标注 } else { final Map<String, Object> param = new ParamMap<Object>(); int i = 0; //4、遍历names集合;{0=id, 1=lastName,2=2} for (Map.Entry<Integer, String> entry : names.entrySet()) { //names集合的value作为key; names集合的key又作为取值的参考args[0]:args【1,"Tom"】: //eg:{id=args[0]:1,lastName=args[1]:Tom,2=args[2]} param.put(entry.getValue(), args[entry.getKey()]); // add generic param names (param1, param2, ...)param //额外的将每一个参数也保存到map中,使用新的key:param1...paramN //效果:有Param注解可以#{指定的key},或者#{param1} 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; } } } ===========================参数值的获取====================================== #{}:可以获取map中的值或者pojo对象属性的值; ${}:可以获取map中的值或者pojo对象属性的值; select * from tbl_employee where id=${id} and last_name=#{lastName} Preparing: select * from tbl_employee where id=2 and last_name=? 区别: #{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入 ${}:取出的值直接拼装在sql语句中;会有安全问题; 大多情况下,我们去参数的值都应该去使用#{}; 原生jdbc不支持占位符的地方我们就可以使用${}进行取值 比如分表、排序。。。;按照年份分表拆分 select * from ${year}_salary where xxx; select * from tbl_employee order by ${f_name} ${order} #{}:更丰富的用法: 规定参数的一些规则: javaType、 jdbcType、 mode(存储过程)、 numericScale、 resultMap、 typeHandler、 jdbcTypeName、 expression(未来准备支持的功能); jdbcType通常需要在某种特定的条件下被设置: 在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错); JdbcType OTHER:无效的类型;因为mybatis对所有的null都映射的是原生Jdbc的OTHER类型,oracle不能正确处理; 由于全局配置中:jdbcTypeForNull=OTHER;oracle不支持;两种办法 1、#{email,jdbcType=OTHER}; 2、jdbcTypeForNull=NULL <setting name="jdbcTypeForNull" value="NULL"/>
pagehelper
官方文档地址
https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md
Hibernate与Mybatis的区别
视频01
使用基本流程(不与spring配合的情况下)
Resource类
帮助加载全局配置文件,辅助SqlSessionFactoryBuilder创建SqlSessionFactory对象
SqlSessionFactoryBuilder
创建SqlSessionFactory对象
SqlSessionFactory
MyBatis的核心对象,用于生成SqlSession对象
SqlSession
直接与数据库交流的类,在使用时每次与数据库的交互都需要创建一个SqlSession类,并且使用完成后需要关闭,SqlSession是非线程安全的,在使用时要用一次new一次,然后关闭,不要作为类的属性使用
使用方式
旧用法(selectOne)
新用法(接口式编程)
xml文件中的namespeace与接口的全文件名一致,id与接口中的方法名一致,即可映射,无需其他配置
mybatis整合spring
中文官方文档网址 http://www.mybatis.org/spring/zh/index.html
mybatis逆向工程
根据数据库表格自动生成实体类,mapper.java等
使用步骤
创建mgb.xml(名称任意)配置文件
配置文件示例
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="DB2Tables" targetRuntime="MyBatis3"> <!-- 指定如何连接到目标数据库 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="123456"> </jdbcConnection> <!-- java类型解析器 --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- 指定javabean的生成策略 targetPackage="test.model":指定目标包名 targetProject=".\src":指定目标工程 --> <javaModelGenerator targetPackage="com.lcs.mybatis.bean" targetProject=".\src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- 指定sql映射的生成策略 --> <sqlMapGenerator targetPackage="com.lcs.mybatis.mapper" targetProject=".\conf"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- 指定mapper接口的生成策略 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.lcs.mybatis.mapper" targetProject=".\src"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 指定要逆向分析哪些表:根据表要创建javabean --> <table tableName="tbl_employee" domainObjectName="Employee"> </table> <table tableName="department" domainObjectName="Department"></table> </context> </generatorConfiguration>
配置文件可以放在项目文件下的最高级别(与src目录同级)
执行代码
List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("mbg.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null);
mybatis插件开发
四大对象
executor
parameterhandler
resultsethandler
statementhandler
Interceptor接口
接口中的方法
intercept
拦截目标对象方法的执行
plugin
包装目标对象 所谓包装,指为目标对象创建一个代理对象
setProperties
将插件注册时的properties设置进来
<plugins> <plugin interceptor="com.lcs.mybatis.mapper.MyFirstPlugin"> <property name="user" value="root"/> <property name="password" value="password"/> </plugin> </plugins> property中设置的属性会作为插件类的setProperties方法的参数,在这个方法中可以使用
具体步骤
1.创建一个类,继承Interceptor接口
2.重写其中的方法
3.添加注解 @Intercepts
写法示例
@Intercepts( {@Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)} ) statementhandler:指定要拦截的类 method:指定要拦截的方法 args:指定方法的参数
4.将插件注册到全局配置文件中
插件包装和执行的顺序
按照在全局配置文件中的配置顺序进行包装,先包装的插件的方法后执行
mybatis-config.xml
MyBatis的核心配置文件,包含下列标签,这些标签在书写时必须保持固定的顺序
properties
属性 用于加载properties文件,供mybatis-config.xml的其他标签中调用
resource:引入类路径下的资源
url:引入网络路径或者磁盘路径下的资源
settings
设置 可以包含一系列的设置标签,用以控制MyBatis的行为
configurationFactory
指定一个提供Configuration实例的类。 这个被返回的Configuration实例用来加载被反序列化对象的懒加载属性值。 这个类必须包含一个签名方法static Configuration getConfiguration(). (从 3.2.3 版本开始)
lazyLoadingEnabled
延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。
aggressiveLazyLoading
当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods).
multipleResultSetsEnabled
是否允许单一语句返回多结果集(需要兼容驱动)。
useColumnLabel
使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。
useGeneratedKeys
允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。
autoMappingBehavior
指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)
autoMappingUnknownColumnBehavior
指定发现自动映射目标未知列(或者未知属性类型)的行为。 NONE: 不做任何反应 WARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN) FAILING: 映射失败 (抛出 SqlSessionException)
defaultExecutorType
配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。
defaultStatementTimeout
设置超时时间,它决定驱动等待数据库响应的秒数。
defaultFetchSize
为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。
safeRowBoundsEnabled
允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false。
safeResultHandlerEnabled
允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为false。
cacheEnabled
全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。
localCacheScope
MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。
jdbcTypeForNull
当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。
lazyLoadTriggerMethods
指定哪个对象的方法触发一次延迟加载。
defaultScriptingLanguage
指定动态 SQL 生成的默认语言。
defaultEnumTypeHandler
指定 Enum 使用的默认 TypeHandler 。 (从3.4.5开始)
callSettersOnNulls
指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。
returnInstanceForEmptyRow
当返回行的所有列都是空时,MyBatis默认返回null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (i.e. collectioin and association)。(从3.4.2开始)
logPrefix
指定 MyBatis 增加到日志名称的前缀。
logImpl
指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
proxyFactory
指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。
vfsImpl
指定VFS的实现
useActualParamName
允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。(从3.4.1开始)
mapUnderscoreToCamelCase
是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。
typeAliases
类型别名 用以给较长的字符串设置一个较短的别名,简化书写 别名在使用时不区分大小写 mybatis已经为java中的一些基本的类型起好别名了, 在使用时注意自己写的别名不要与mybatis的别名冲突
package
name:为一个包包括其子包的所有类起一个默认的别名(类名小写)
typeAlias
type:指定全类名
alias:指定别名,不指定的话会有默认的别名,就是全类名中的类名小写
@Alias注解
typeHandlers
类型处理 用以处理java属性的类型与数据库属性类型之间的转换
objectFactory
对象工厂
plugins
插件
environments
环境配置
transactionManager
dataSource
databaseIdProvider
数据库厂商标识
mappers
映射器 用来指定需要映射的Mapper文件,其中的mapper选项卡中可以有四种指定方式
mapper
mappers下的子标签,根据属性的不同,用以加载xml文件或者接口
resource
引入类路径下的sql映射文件
url
引入网络路径或磁盘路径下的sql映射文件
class
使用class属性时,加载的是接口文件,此时需保证接口文件与对应的xml文件在同一个包下,同时名称需要对应
package
指定全部加载某个包,把包中的接口和xml文件全部加载,并根据名称一一对应
mybatis也可以不写xml文件,而直接在接口文件上以注解的方式注册sql
注解示例:@Select,@insert...
缓存
一级缓存
默认开启,SqlSession级别的缓存,也称为本地缓存 与数据库同一次会话期间查询到的数据会放在本地缓存中,以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库 相当于SqlSession级别的一个map
一级缓存的失效情况
1.SqlSession不同
2.SqlSession相同,但是查询条件不同(当前一级缓存中还没有这个数据)
3.SqlSession相同,但两次查询之间执行了增删改操作
4.SqlSession相同,但手动清除了一级缓存(调用clearCache方法)
二级缓存
namespace级别的缓存,需要手动开启和配置 一个namespeace对应一个二级缓存
二级缓存是基于namespace的
二级缓存的工作机制
1、一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
2、如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;
3.不同namespace查出的数据会放在自己对应的缓存中(map)
效果:数据会从二级缓存中获取,查出的数据都会被默认先放在一级缓存中。只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中
二级缓存的使用
使用: 1)、开启全局二级缓存配置: 在全局配置文件的settings标签中加入: <setting name="cacheEnabled" value="true"/> 2)、去mapper.xml中配置使用二级缓存: <cache></cache> cache标签中的属性 eviction:缓存的回收策略: • LRU – 最近最少使用的:移除最长时间不被使用的对象。 • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。 • 默认的是 LRU。 flushInterval:缓存刷新间隔,缓存多长时间清空一次,默认不清空,设置一个毫秒值 readOnly:是否只读:(true或者false)(默认是false) true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。 mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快 false:非只读:mybatis觉得获取的数据可能会被修改。 mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢 size:缓存存放多少元素; type="":指定自定义缓存的全类名; 实现Cache接口即可; 3)、我们的POJO(plain object java objection,其实也就是实体类)需要实现序列化接口
缓存有关的设置以及属性
具体内容
和缓存有关的设置/属性: 1)、cacheEnabled=true:false:关闭缓存(二级缓存关闭,一级缓存可用) 2)、每个select标签都有useCache="true": false:不使用缓存(一级缓存依然使用,二级缓存不使用) 3)、【每个增删改标签的:flushCache="true":(一级二级都会清除)】 增删改执行完成后就会清楚缓存; 测试:flushCache="true":一级缓存就清空了;二级也会被清除; 查询标签:flushCache="false": 如果flushCache=true;每次查询之后都会清空缓存;缓存是没有被使用的; 4)、sqlSession.clearCache();只是清楚当前session的一级缓存; 5)、localCacheScope:本地缓存作用域:(一级缓存SESSION);当前会话的所有数据保存在会话缓存中; STATEMENT:可以禁用一级缓存;
cacheEnabled
useCache
对一级缓存没有影响,但对二级缓存有影响
flushCache
sqlSession.clearCache()
localCacheScope
中文翻译:本地缓存作用域 setting中的设置,默认值为session和statement 当值为statement时,可以关闭一级缓存
缓存的使用顺序
如果二级缓存开启的话,先检查二级缓存,在检查一级缓存,最后都没有,再去数据库中查询数据
mybatis整合ehcache
需要导入ehcache的jar包,具体使用请看视频
第三方缓存整合
1.导入第三方缓存包 2.导入与第三方缓存整合的适配包(官方有) 3.mapper.xml中使用自定义缓存
mapper.xml
MyBatis的核心配置文件之一,用以书写sql等功能
cache-ref
配置在xml文件中,用于引入其他xml文件的cache标签的配置,开启相同的二级缓存 具体使用为配置其中的namespace标签,用于指定被引入的对象
delete
update
select
resultType
resultMap
id
select返回List集合
resaultType写成集合中的元素就好了
select返回Map
resaultType="map"
select返回特殊map,Map的value是实体类,key是实体类中的一个属性
利用@MapKey注解(在mapper接口的方法上添加) MapKey中填写数据库的字段名
resultMap
也叫自定义结果集 用于自定义某个javabean的封装规则
resaultMap标签内部属性
自定义某个javabean的封装规则
type
填写javabean的名称,如果没有起别名的话,需要填写完成的类型
id
识别标志
下属标签
通过下属标签可以指定映射规则,没有被指定的数据库中的列可以自动映射,但是推荐全部指定
id
标签内部属性
column
数据库中的列
property
数据库中的列要对应的映射的类中的属性 如果要封装到的属性,,是实体类中一个对象类型变量之中的属性,可以通过--变量.属性--的方式来封装
resault
非主键列的定义标签 主键列也可以用resault定义,但是用id定义的话,可以享受内部的优化规则
column
property
数据库中的列要对应的映射的类中的属性 如果要封装到的属性,,是实体类中一个对象类型变量之中的属性,可以通过--变量.属性--的方式来封装
association
内部属性
property
指定哪个属性是要联合的对象
javaType
指定要联合的对象的类型
select
指明调用的方法的名称,用于分步查询
column
与select配合使用,值等于要给select中指定的方法的参数
fenthType
影响延迟加载的属性,使用时会覆盖setting中的延迟加载的设置
lazy
使用延迟加载
eager
立即加载
内部标签
id
resault
使用association进行分步查询
property:要映射的实体类中的对象类型属性 select:映射属性需要调用的方法 column:要传输给select中指定的方法的产生银行 流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的对象
分步查询的好处
1.组合已有的方法完成功能
2.可以使用延迟加载
使用时需要在setting中添加配置
lazyLoadingEnable>>true
aggressiveLazyLoading>>false
在配置完成后,被分步查询的实体类中的对象类型只有在被使用时才会去查询并加载
association用于定义对象类型属性,collection用于定义集合类型的属性
collection
嵌套结果集的方式,定义关联的集合类型元素的封装规则
内部属性
property
用于指定要映射的实体类中的集合类型属性的名称
ofType
指定要映射的集合中的元素的类型
fenthType
lazy
使用延迟加载
eager
立即加载
内部标签
id
resault
使用collection进行分步查询
property:指定要映射到的集合类型属性的名称 select:指定要使用的方法 column:用于指定传输给select中的方法的属性
延迟加载的用法和association中一样
association和collection中的column属性传递多个值
将多列的值封装成为Map传递 column={key1=column1,key2=column2}
discriminator
可以判断某列的值,然后根据不同的值改变封装行为
内部属性
javaType
column
case
用于case到需要的值
内部属性
value
指定要case的值
resultType
关联查询
级联属性
association
collection
insert
在插入过程中获取自增主键的值
MySQL
在insert标签中添加 useGererateKey="true" KeyProperty=""(设置成要映射到的类的属性的名称) sql语句执行完成后,在输出被映射的类的指定属性即可输出返回的key值
Oracle
Oracle不支持主键自增,但维护一个保存目前已经使用过的最大值得表,在想要以主键自增的形式插入数据时,需要与这张表配合操作 通过这张表与selectKey标签来配合,获得主键
selectKey
keyProperty
设置要被映射的类的属性
resaultType
返回值的类型
order
决定selectKey中的语句的执行实在主语句之前还是之后
${}与#{}中可以使用的标签
javaType
可以用来处理向oralce插入null的情况
jdbcType
mode
numericScale
resultMap
typeHandler
jdbcTypeName
oralce中插入null的处理
视频25
parameterType
动态SQL
if
test
判断表达式
include
trim
trim标签体中是整个字符串拼接后的结果 可以用来调整字符串拼接后的结果,在一定程度上可以替代where和set标签
标签属性
prefix
前缀 给拼接后的整个字符串加一个前缀
prefixOverrides
前缀覆盖 去掉整个字符串前面多余的字符,具体去掉什么看填写的值
suffix
后缀 给拼接后的整个字符串加一个后缀
suffixOverrides
后缀覆盖 去掉整个字符串后面多余的字符,具体去掉什么看填写的值
choose
下属标签
when
otherwise
OGNL表达式
具体的使用参照ppt或者官方文档 在其中使用特殊符号(例如XML中的特殊符号)的时候要使用转义字符
set
封装修改条件 和where不同,set可以去掉后面的逗号
where标签
封装查询条件 在拼接查询条件的时候,可以将多出的and或者or去掉 但是只会去掉位于前方的多出的第一个and或者or 所以在使用where标签的时候,and最好写在前方
内置参数
在使用动态参数时可以使用这两个参数进行判断,取值等操作
_parameter
代表整个参数 单个参数:_parameter就是这个参数 多个参数:参数会被封装为一个map,_parameter就是代表这个map
即使不使用动态sql,只要在xml文件中,这两个参数都是可以使用的
_databaseId
如果配置了databaseIdProvider标签。 _databaseId就是代表当前数据库的别名
bind
可以将OGNL表达式的值,绑定到一个变量中,方便后来引用这个变量的值 bind标签的value属性中可以使用"+"进行字符串拼接
sql
sql用来抽取,include用来引用,include还可以自定义一些property属性,sql也可以引用这些属性
foreach
标签属性
collection
指定要遍历的集合
item
将当前遍历出的元素赋值给指定的变量
separator
每个元素之间的分隔符
open
指定拼接后的字符串的开头
close
指定拼接后的字符串以什么结束
index
遍历list的时候,index就是索引,item就是值 遍历map的时候,index就是key,item就是value
mysql下批量插入数据
利用一条插入语句同时插入多条数据
发送多条sql语句进行插入,需要"allowMultiQueries=true"的支持
这个属性需要添加在数据库连接路径配置文件中的url的问号后面
这种方式也可以用于其他的批量操作
MySQL下批量保存和Oracle下不一样
MySQL下批量保存和Oracle下不一样
Oracle下批量插入数据
Oracle不支持values(),(),()
oracle数据库的两种遍历方式
1、多个insert放在begin - end里面
begin insert into employees(employee_id,last_name,email) values(employees_seq.nextval,'test_001','test_001@atguigu.com'); insert into employees(employee_id,last_name,email) values(employees_seq.nextval,'test_002','test_002@atguigu.com'); end;
mapper.xml文件示例
<insert id="addEmps" databaseId="oracle"> <!-- oracle第一种批量方式 --> <foreach collection="emps" item="emp" open="begin" close="end;"> insert into employees(employee_id,last_name,email) values(employees_seq.nextval,#{emp.lastName},#{emp.email}); </foreach> </insert>
MySQL下批量保存和Oracle下不一样
MySQL下批量保存和Oracle下不一样
2、利用中间表
insert into employees(employee_id,last_name,email) select employees_seq.nextval,lastName,email from( select 'test_a_01' lastName,'test_a_e01' email from dual union select 'test_a_02' lastName,'test_a_e02' email from dual union select 'test_a_03' lastName,'test_a_e03' email from dual )
mapper.xml文件示例
<insert id="addEmps" databaseId="oracle"> <!-- oracle第二种批量方式 --> insert into employees( <!-- 引用外部定义的sql --> <include refid="insertColumn"> <property name="testColomn" value="abc"/> </include> ) <foreach collection="emps" item="emp" separator="union" open="select employees_seq.nextval,lastName,email from(" close=")"> select #{emp.lastName} lastName,#{emp.email} email from dual </foreach> </insert>
MySQL下批量保存和Oracle下不一样
cache
配置在xml文件中,用于开启二级缓存
${}与#{}取值的区别
接口(mapper.java)
insert-增
方法的返回值可以为 void;什么也不返回 Integer:受到影响的行数 Long:受到影响的行数 Boolean:如果受影响的行数大于一,则返回true,否则返回false
@Param
delete-删
方法的返回值可以为 void;什么也不返回 Integer:受到影响的行数 Long:受到影响的行数 Boolean:如果受影响的行数大于一,则返回true,否则返回false
@Param
update-改
方法的返回值可以为 void;什么也不返回 Integer:受到影响的行数 Long:受到影响的行数 Boolean:如果受影响的行数大于一,则返回true,否则返回false
@Param
select-查
@Param
@MapKey
参数传递
单个参数
多个参数
命名参数
POJO
Map
参数的传递原理(源代码)
mybatis运行原理
1、获取sqlSessionFactory对象: 解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession; 注意:【MappedStatement】:代表一个增删改查的详细信息 2、获取sqlSession对象 返回一个DefaultSQlSession对象,包含Executor和Configuration; 这一步会创建Executor对象; 3、获取接口的代理对象(MapperProxy) getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象 代理对象里面包含了,DefaultSqlSession(Executor) 4、执行增删改查方法 总结: 1、根据配置文件(全局,sql映射)初始化出Configuration对象 2、创建一个DefaultSqlSession对象, 他里面包含Configuration以及 Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor) 3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy; 4、MapperProxy里面有(DefaultSqlSession); 5、执行增删改查方法: 1)、调用DefaultSqlSession的增删改查(Executor); 2)、会创建一个StatementHandler对象。 (同时也会创建出ParameterHandler和ResultSetHandler) 3)、调用StatementHandler预编译参数以及设置参数值; 使用ParameterHandler来给sql设置参数 4)、调用StatementHandler的增删改查方法; 5)、ResultSetHandler封装结果 注意: 四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);
查询基本调用流程
代理对象
DefaultSqlsession
executor
statementhandler
parameterhandler
typehandler
resaultsethandler
 
  
  
  
  
  
  
  
  
 