作用:将数据连接单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值,在SqlMapConfig.xml中就不需要对数据库连接参数进行硬编码。数据库连接参数只配置在db.properties中,方便对参数进行统一管理,其它xml可以引用该db.properties。
db.properties的内容:
jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/mybatisjdbc.username=rootjdbc.password=root
在SqlMapConfig.xml中加载db.properties
<!-- 加载数据库文件db.properties --><properties resource="db.properties"> <!-- properties中还可以配置一些属性名和属性值,此处的优先加载 --> <!-- <property name="driver" value=""/> --> </properties> <!-- 和spring整合后 environments配置将废除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理,事务控制由mybatis管理--> <transactionManager type="JDBC" /> <!-- 数据库连接池,由mybatis管理--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments>
properties特性:
注意:
建议:
不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
在properties文件中定义属性名要有一定的特殊性,如xxxx.xxxx(jdbc.driver)
三:settings全局参数配置mybatis框架运行时可以调整一些运行参数。比如,开启二级缓存,开启延迟加载等等。全局参数会影响mybatis的运行行为。
mybatis-settings的配置属性以及描述
setting(设置) | Description(描述) | valid Values(验证值组) | Default(默认值) |
cacheEnabled | 在全局范围内启用或禁用缓存配置 任何映射器在此配置下。 | true | false | TRUE |
lazyLoadingEnabled | 在全局范围内启用或禁用延迟加载。禁用时,所有相关联的将热加载。 | true | false | TRUE |
aggressiveLazyLoading | 启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。 | true | false | TRUE |
multipleResultSetsEnabled | 允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。 | true | false | TRUE |
useColumnLabel | 使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 | true | false | TRUE |
useGeneratedKeys | 允许JDBC支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为true,一些驱动会不兼容性,但仍然可以工作。 | true | false | FALSE |
autoMappingBehavior | 指定MyBatis的应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL只会自动映射结果没有嵌套结果映射定义里面。 FULL会自动映射的结果映射任何复杂的(包含嵌套或其他)。 | NONE,PARTIAL,FULL | PARTIAL |
defaultExecutorType | 配置默认执行人。SIMPLE执行人确实没有什么特别的。 REUSE执行器重用准备好的语句。 BATCH执行器重用语句和批处理更新。 | SIMPLE,REUSE,BATCH | SIMPLE |
safeRowBoundsEnabled | 允许使用嵌套的语句RowBounds。 | true | false | FALSE |
mapUnderscoreToCamelCase | 从经典的数据库列名A_COLUMN启用自动映射到骆驼标识的经典的Java属性名aColumn。 | true | false | FALSE |
localCacheScope | MyBatis的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果localCacheScope=STATMENT本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的SqlSession。 | SESSION STATEMENT | SESSION |
dbcTypeForNull | 指定为空值时,没有特定的JDBC类型的参数的JDBC类型。有些驱动需要指定列的JDBC类型,但其他像NULL,VARCHAR或OTHER的工作与通用值。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定触发延迟加载的对象的方法。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定所使用的语言默认为动态SQL生成。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags .XMLDynamicLanguageDriver |
callSettersOnNulls | 指定如果setter方法??或地图的put方法时,将调用检索到的值是null。它是有用的,当你依靠Map.keySet()或null初始化。注意原语(如整型,布尔等)不会被设置为null。 | true | false | FALSE |
logPrefix | 指定的前缀字串,MyBatis将会增加记录器的名称。 | Any String | Not set |
logImpl | 指定MyBatis的日志实现使用。如果此设置是不存在的记录的实施将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | 指定代理工具,MyBatis将会使用创建懒加载能力的对象。 | CGLIB | JAVASSIST | CGLIB |
官方文档settings的例子
<setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/></settings>View Code四:typeAiases(别名)--重点掌握
在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。
如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
4.1.mybatis默认支持的别名
别名 | 映射的类型 |
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
4.2.自定义别名
4.2.1:单个别名定义(在SqlMapConfig.xml)
<!-- 别名定义:针对单个别名定义 type:类型的路径; alias:别名 --> <typeAliases><typeAlias type="com.mybatis.entity.User" alias="user"/></typeAliases>
UserMapper.xml引用别名:
<select id="findUserById" parameterType="int" resultType="user" > select * from t_user where id=#{id}</select>
4.2.2:批量定义别名(常用)
<!-- 批量别名的定义: package:指定包名,mybatis会自动扫描包中的pojo类,自动定义别名,别名就是类名(首字母大写或小写都可以) --> <typeAliases> <package name="com.mybatis.entity"/> <package name="其它包"/> </typeAliases>五:typeHandlers(类型处理器)
mybatis中通过typeHandlers完成jdbc类型和java类型的转换。
通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.
mybatis支持类型处理器:
类型处理器 | Java类型 | JDBC类型 |
BooleanTypeHandler | Boolean,boolean | 任何兼容的布尔值 |
ByteTypeHandler | Byte,byte | 任何兼容的数字或字节类型 |
ShortTypeHandler | Short,short | 任何兼容的数字或短整型 |
IntegerTypeHandler | Integer,int | 任何兼容的数字和整型 |
LongTypeHandler | Long,long | 任何兼容的数字或长整型 |
FloatTypeHandler | Float,float | 任何兼容的数字或单精度浮点型 |
DoubleTypeHandler | Double,double | 任何兼容的数字或双精度浮点型 |
BigDecimalTypeHandler | BigDecimal | 任何兼容的数字或十进制小数类型 |
StringTypeHandler | String | CHAR和VARCHAR类型 |
ClobTypeHandler | String | CLOB和LONGVARCHAR类型 |
NStringTypeHandler | String | NVARCHAR和NCHAR类型 |
NClobTypeHandler | String | NCLOB类型 |
ByteArrayTypeHandler | byte[] | 任何兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB和LONGVARBINARY类型 |
DateTypeHandler | Date(java.util) | TIMESTAMP类型 |
DateOnlyTypeHandler | Date(java.util) | DATE类型 |
TimeOnlyTypeHandler | Date(java.util) | TIME类型 |
SqlTimestampTypeHandler | Timestamp(java.sql) | TIMESTAMP类型 |
SqlDateTypeHandler | Date(java.sql) | DATE类型 |
SqlTimeTypeHandler | Time(java.sql) | TIME类型 |
ObjectTypeHandler | 任意 | 其他或未指定类型 |
EnumTypeHandler | Enumeration类型 | VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。 |
6.1:通过resource加载单个映射文件
<!-- 加载映射文件 --> <mappers> <!--通过resource方法一次加载一个映射文件 --> <mapper resource="sqlmap/User.xml"/> <mapper resource="mapper/UserMapper.xml"/> </mappers>
6.2:通过mapper接口加载单个映射文件
<!-- 通过mapper接口加载单个映射配置文件 遵循一定的规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中; 上边规范的前提是:使用的是mapper代理方法; --> <mapper class="com.mybatis.mapper.UserMapper"/>
按照上边的规范,将mapper.java和mapper.xml放在一个目录 ,且同名。
6.3:批量加载mapper(推荐使用)
<!-- 批量加载映射配置文件,mybatis自动扫描包下面的mapper接口进行加载 遵循一定的规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中; 上边规范的前提是:使用的是mapper代理方法; --> <package name="com.mybatis.mapper"/>
mybatis入门基础(三)----SqlMapConfig.xml全局配置文件解析
标签:
小编还为您整理了以下内容,可能对您也有帮助:
Mybatis的基础和高级查询应用实践
将分为3部分介绍:
#java# #数据库# #开发# #后端#
快速入门查看官网 :http://www.mybatis.org/mybatis-3
1.添加Mybatis的坐标(添加pom.xml依赖)
2.创建数据库表 + 编写实体
表设计和实体根据自己业务实际编写即可
3.编写映射文件Mapper.xml与标签说明
4.编写核心文件SqlMapConfig.xml
5.使用
: 数据库环境的配置,支持多种环境配置
: 环境变量
: 事务管理器,有两种类型:
: 数据源,有三种类型:
: 属性
: 属性该标签可以加载额外配置的properties文件,如resource文件夹下的jdbc.properties。使用方式为:${jdbc.driver} 可以引用对应的值
: 映射器,作用是加载sql的映射,有四种方式
从用户角度出发,查询一对多结果;
用户和角色的关系,就是多对多查询;
代替了标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。有以下属性:
代替了标签,是多表查询的关键,再注解中用来指定子查询返回的对象集合。有以下属性:
以上是对mybatis的基础使用和高级用法,实际项目中,可以结合情况,使用xml查询或者使用两者结合查询都是可行的。
快捷访问:Mybatis一级缓存和二级缓存
MyBatis解析
从命名上可以看出,这个是一个 Builder 模式的,用于创建 SqlSessionFactory 的类。SqlSessionFactoryBuilder 根据配置来构造 SqlSessionFactory。其中配置方式有两种:
mybatis-config.xml 就是我们的配置文件:
Java Config 相比较 XML 文件的方式而言,会有一些。比如修改了配置文件需要重新编译,注解方式没有 XML 配置项多等。所以,业界大多数情况下是选择 XML 文件的方式。但到底选择哪种方式,这个要取决与自己团队的需要。比如,项目的 SQL 语句不复杂,也不需要一些高级的 SQL 特性,那么 Java Config 则会更加简洁一点;反之,则可以选择 XML 文件的方式。
创建配置文件解析器XMLConfigBuilder
解析mybatis-config.xml里的配置为Configuration对象,Mybatis的全局配置对象。
XMLConfigBuilder#parseConfiguration解析mapper下的xml
XMLMapperBuilder#bindMapperForNamespace,根据xml里的 namespace 反射出 mapper接口 的 class,如果有mapper接口,则把该mapper接口的class添加到Configuration的mapperRegistry里。
如果该接口已经注册,则抛出已经绑定的异常。
为该接口注册MapperProxyFactory,但这里只是注册其创建MapperProxy的工厂,并不是创建MapperProxy。
如果Mapper对应的xml资源未加载,触发xml的绑定操作,将xml中的sql语句与Mapper建立关系。
addMapper方法,只是为**Mapper创建对应对应的MapperProxyFactory。
根据Mapper接口与SqlSession创建MapperProxy对象。
根据接口类获取MapperProxyFactory。
调用MapperProxyFactory的newInstance创建MapperProxy对象。
SqlSessionFactory 顾名思义,是用于生产 SqlSession 的工厂。 通过如下的方式来获取 SqlSession 实例:
SqlSession 包含了执行 SQL 的所有的方法。以下是示例:
当然,下面的方式可以做到类型安全:
MapperProxy是MapperProxyFactory使用SqlSession创建出来的。所以MapperProxy中包含SqlSession。
可以看到MapperProxy调用invoke方法,进而调用MapperMethod的execute(),这些MapperMethod就是和你要执行的命令相关,比如执行select语句,则会通过SqlSession的select()方法,最终调用到Executor的query方法。Executor会再协调另外三个核心组件。
MapperProxy:
MapperMethod:
插件的构建:
谈原理首先要知道StatementHandler,ParameterHandler,Result Handler都是代理,他们是Configuration创建,在创建过程中会调用interceptorChain.pluginAll()方法,为四大组件组装插件(再底层是通过Plugin.wrap(target,XX, new Plugin( interceptor))来来创建的)。
插件链是何时构建的:
在执行SqlSession的query或者update方法时,SqlSession会通过Configuration创建Executor代理,在创建过程中就调用interceptor的pluginAll方法组装插件。然后executor在调用doQuery()方法的时候,也会调用Configuration的newStatementHandler方法创建StatemenHandler(和上面描述的一样,这个handler就是个代理,也是通过interceptorChain的pluginAll方法构建插件)
插件如何执行:
以statementhandler的prepare方法的插件为例,正如前面所说,statementhandler是一个proxy,执行他的prepare方法,将调用invokeHandler的invoke方法,而invokeHandler就是Plugin.wrap(target, xxx, new Plugin(interceptor))中的第三个参数,所以很自然invokeHanlder的invoke的方法最终就会调用interceptor对象的intercept方法。
Mybatis的插件配置在configuration内部,初始化时,会读取这些插件,保存于Configuration对象的InterceptorChain中。
org.apache.ibatis.plugin.InterceptorChain.java源码。
上面的for循环代表了只要是插件,都会以责任链的方式逐一执行,所谓插件,其实就类似于。
插件的编写
插件必须实现org.apache.ibatis.plugin.Interceptor接口。
-intercept()方法:执行拦截内容的地方,拦截目标对象的目标方法的执行
-plugin()方法:决定是否触发intercept()方法。 作用:包装目标对象,包装就是为目标对象创建一个代理对象
-setProperties()方法:给自定义的传递xml配置的属性参数。将插件注册时的property属性设置进来
下面自定义一个:
为什么要写Annotation注解?注解都是什么含义?
Mybatis规定插件必须编写Annotation注解,是必须,而不是可选。@Intercepts注解:装载一个@Signature列表,一个@Signature其实就是一个需要拦截的方法封装。那么,一个要拦截多个方法,自然就是一个@Signature列表。
type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }
解释:要拦截Executor接口内的query()方法,参数类型为args列表。
Plugin.wrap(target, this)是干什么的?
使用JDK的动态代理,给target对象创建一个delegate代理对象,以此来实现方法拦截和增强功能,它会回调intercept()方法。
Mybatis可以拦截哪些接口对象?
Mybatis只能拦截ParameterHandler、ResultSetHandler、StatementHandler、Executor共4个接口对象内的方法。
重新审视interceptorChain.pluginAll()方法:该方法在创建上述4个接口对象时调用,其含义为给这些接口对象注册功能,注意是注册,而不是执行拦截。
执行时机:plugin()方法注册后,那么,在执行上述4个接口对象内的具体方法时,就会自动触发的执行,也就是插件的执行。
Invocation
可以通过invocation来获取拦截的目标方法,以及执行目标方法。
分页插件原理
由于Mybatis采用的是逻辑分页,而非物理分页,那么,市场上就出现了可以实现物理分页的Mybatis的分页插件。 要实现物理分页,就需要对String sql进行拦截并增强,Mybatis通过BoundSql对象存储String sql,而BoundSql则由StatementHandler对象获取。
因此,就需要编写一个针对StatementHandler的query方法,然后获取到sql,对sql进行重写增强。
mybatismap怎么根据缓存查询mybatis的缓存
如何使用mybatisL2缓存?
了解更多关于MyBatisL2缓存的信息首先,创建缓存的整个过程
我们从SqlSessionFactoryBuilder解析mybatis-config.xml配置文件开始:
readerreader=resources.getresourceasreader(mybatis-config.XML);
SqlSessionFactorySqlSessionFactory=newSqlSessionFactorybuilder()。构建(阅读器);
然后:
XMLConfigBuilderparser=newXMLConfigBuilder(inputStream,environment,properties);
返回build(parser.parse());
看看parser.parse()方法:
parseconfiguration(parser.evalnode(/配置
查看处理Mapper.xml文件的位置:
mapperelement(root.evalnode(地图绘制者
看看处理Mapper.xml的XMLMapperBuilder:
XMLmapperbuildermapperparser=newXMLmapperbuilder(inputStream,configuration,
resource,configuration.getsqlfragments());
mapperparser.parse();
继续看看解析方法:
configurationelement(parser.evalnode/mapper));
转到此处:
stringnamespace=context.getstringattribute(命名空间
if(namespace.equals(映射器的命名空间不能为空);
}
builderassistant.setcurrentnamespace(命名空间);
cacheRefElement(context.evalnode(cache-ref));
cacheElement(context.evalnode(缓存
看这里,名称空间是
看看我的巴蒂斯如何处理
私有voidcacheElement(XNode上下文)引发异常{
如果(上下文!=null){
stringtype=context.getstringattribute(键入
Class
stringeviction=context.getstringattribute(驱逐);
Class
longflushinterval=context.getlongattribute(flushInterval
integersize=context.getintattribute(尺寸
布尔读写=!context.getbooleanattribute(只读,假);
booleanblocking=context.getbooleanattribute(阻止
propertiesprops=context.getchildrenaspproperties();
builderasistant.usenewcache(typeclass,evictionClass,
flushInterval、size、readWrite、blocking、props);
}
}
从源代码中可以看到MyBatis已经读取了那些属性,很容易就可以得到这些属性的默认值。
Java的cache对象方法是builderAssistant.useNewCache我们来看看这段代码:
公共缓存useNewCache(Class马鞭延伸缓存
evictionclass=valueOrDefault(evictionclass,lrucache.class);
Cachecache=新的CacheBuilder(当前命名空间)
.实现(类型类)
.addDecorator(evictionClass)
.清除时间间隔
.尺寸(大小)
.读写(读写)
.阻断(阻断)
.属性(道具)
.build();
configuration.addCache(缓存);
currentCache=cache
返回缓存;
}
从调用这个方法的地方我们可以看到,并没有使用返回值缓存,而是在后面的过程中创建MappedStatement时使用了currentCache。
第二,使用缓存过程
在系统中,使用缓存的地方是在CachingExecutor中:
@覆盖
公共
获取缓存后,先确定是否有二级缓存。
仅通过,
然后根据xml配置的属性useCache判断是否使用缓存(resultHandler常用的默认值很少为null)。
if(ms.isusecache()
如果没有问题,将根据键从缓存中获取值:
@suppresswarnings(未选中E
如果没有缓存,将执行查询,并将查询结果放入缓存中。
if(list==null){
列表=委托。
tcm.putObject(缓存、键、列表);//问题#578和#116
}
返回结果
退货单;
}
}
没有缓存时,直接执行查询。
返回委托。
}
在上面的代码中,tcm.putObject(cache,key,list);这段代码缓存结果。但实际上,直到sqlsession关闭,MyBatis才以序列化的形式保存在Map(默认缓存配置)中。
三、使用缓存时的注意事项
1.缓存只能用于具有单表操作的表。
只需要保证这个表在整个系统中只有一个表操作,所有和这个表相关的操作都必须在一个命名空间中。
2.当您可以保证查询远远大于插入、更新和删除操作时,请使用缓存。
这不用我说,大家应该都知道。记住,这需要在1的前提下保证!
第四,避免使用L2缓存。
这里可能有很多人不理解。L2缓存带来的好处远远小于隐患。
缓存在命名空间中,不同命名空间中的操作互不影响。
插入、更新和删除操作将清除空所在的名称空间中的所有缓存。
通常在MyBatisGenerator生成的代码中,每个表都是的,每个表都有自己的命名空间。
为什么避免使用L2缓存?
符合【缓存使用注意事项
mybatiscollection的三种用法?
mybatis使用foreach中collection的三种用法
foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。
foreach元素的属性主要有item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,
index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,
open表示该语句以什么开始,
separator表示在每次进行迭代之间以什么符号作为分隔符,
close表示以什么结束。
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:
1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可
以封装成map,实际上如果你在传入参数的时候,在breast里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key下面分别来看看上述三种情况的示例代码
mybatis怎么将一个表中符合查询条件的多条记录,返回为一个list+map的形式?
xml中配置好pojo对象然后将properties和数据库字段匹配即可