MyBatis配置灵活,支持多种配置方式:
完全代码配置。MyBatis 提供完整的配置类,用户可以调用这些配置类完成所有配置工作。
基于xml的配置方式。
外部框架配置,比如Spring、SoringBoot。
采用xml配置配置数据信息,通常命名为mybatis-config.xml,该 XML文件的根节点为configuration,根节点内可以包含的一级节点及其含义如下所示:
properties:属性信息,相当于 MyBatis的全局变量。settings:设置信息,通过它对 MyBatis的功能进行调整。typeAliases:类型别名,在这里可以为类型设置一些简短的名字。typeHandlers:类型处理器,在这里可以为不同的类型设置相应的处理器。objectFactory:对象工厂,在这里可以指定 MyBatis创建新对象时使用的工厂。objectWrapperFactory:对象包装器工厂,在这里可以指定 MyBatis使用的对象包装器工厂。reflectorFactory:反射器工厂,在这里可以设置 MyBatis的反射器工厂。plugins:插件,在这里可以为 MyBatis 配置插件,从而修改或扩展 MyBatis 的行为。environments:环境,这里可以配置 MyBatis运行的环境信息,如数据源信息等。databaseIdProvider:数据库编号,在这里可以为不同的数据库配置不同的编号,这样可以对不同类型的数据库设置不同的数据库 *** 作语句。mappers:映射文件,在这里可以配置映射文件或映射接口文件的地址。
注意:有严格的顺序
了解了mybatis-config.xml的配置属性对于其他方式的配置也是有所帮助的。
一、properties - 属性
一个比较常用的例子是,设置数据库的url、driver、username、password属性,供配置environment时使用
示例:
定义它:
关于配置属性的优先级从高到低:
- 对象传入的参数设置的(SqlSessionFactoryBuilder.build() 方法中传入属性值)resource|url指定的文件中参数property指定的参数
使用它:
二、settings - 设置
用于调整MyBatis的一些重要参数设置,比如二级缓存等
三、typeAliases - 类型别名
MyBatis对于许多基础的类型设置了别名,同样也可以设置自定义entity类的别名,这样就不需要在映射文件的resultType中写上很长的返回值类型,只需要写上别名即可。
单个的配置:
多个配置:
进行包扫描即可,默认情况下别名为类名的首字母小写的格式(User -> user)
如果名称需要特殊的设置,可以在类上添加@Alias
@Alias("author") public class Author { [。。。] }
四、typeHandlers - 类型处理器
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型
Java内置了43个类型处理器,如果不满足你的需求可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.baseTypeHandler, 并且可以(可选地)将它映射到一个 JDBC 类型。
typeHandlers使用:
typeHandlers标签用于注册自定义的类型处理器。
单个:
多个:
示例:
@MappedJdbcTypes(JdbcType.VARCHAR) @MappedTypes(String.class) public class ExampleTypeHandler extends baseTypeHandler{ @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getString(columnName); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getString(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); } }
1、设置类型处理器所处理的Java类型:
在类型处理器的配置元素(typeHandler 元素)上增加一个 javaType 属性(比如:javaType=“String”);
在类型处理器的类上增加一个 @MappedTypes 注解指定与其关联的 Java 类型列表。 如果在 javaType 属性中也同时指定,则注解上的配置将被忽略。
2、设置相关联的的jdbc类型:
在类型处理器的配置元素上增加一个 jdbcType 属性(比如:jdbcType=“VARCHAR”);
在类型处理器的类上增加一个 @MappedJdbcTypes 注解指定与其关联的 JDBC 类型列表。 如果在 jdbcType 属性中也同时指定,则注解上的配置将被忽略。
3、ResultMap类型处理器的选择:
当在 ResultMap 中决定使用哪种类型处理器时,此时 Java 类型是已知的(从结果类型中获得),但是 JDBC 类型是未知的。 因此 Mybatis 使用 javaType=[Java 类型], jdbcType=null 的组合来选择一个类型处理器。
这意味着使用 @MappedJdbcTypes 注解可以限制类型处理器的作用范围,并且可以确保,除非显式地设置includeNullJdbcType=true,否则类型处理器在 jdbcType=null 的情况下,ResultMap 将不会选择该类型处理器(即便只有一个该Java类型的类型处理器)。
然而从 Mybatis 3.4.0 开始,如果某个 Java 类型只有一个注册的类型处理器,即使没有设置 includeNullJdbcType=true,那么这个类型处理器也会是 ResultMap 使用 Java 类型时的默认处理器。
五、ObjectFactory - 对象工厂
MyBatis每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现。
其中type可以类的全路径名称(xx.xx.MyObjectFactory),也可以是别名(需要你通过typeAliases标签或者@Alias设置),代码如下:
publicClass resolveAlias(String string) { try { if (string == null) { return null; } else { String key = string.toLowerCase(Locale.ENGLISH); Class value; if (this.typeAliases.containsKey(key)) { value = (Class)this.typeAliases.get(key); } else { value = Resources.classForName(string); } return value; } } catch (ClassNotFoundException var4) { throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + var4, var4); } }
六、ObjectWrapperFactory - 对象包装工厂
对象包装工厂,再MyBatis中存在一个默认实现但该实现似乎没什么用:
public class DefaultObjectWrapperFactory implements ObjectWrapperFactory { @Override public boolean hasWrapperFor(Object object) { return false; } @Override public ObjectWrapper getWrapperFor(metaObject metaObject, Object object) { throw new ReflectionException("The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper."); } }
一个比较有用的例子是,MyBatisPlus提供了一个实现,其具体作用是开启map结果集中的key名称,由下划线转换为驼峰命名法的格式:
public class MybatisMapWrapperFactory implements ObjectWrapperFactory { @Override public boolean hasWrapperFor(Object object) { return object instanceof Map; } @SuppressWarnings("unchecked") @Override public ObjectWrapper getWrapperFor(metaObject metaObject, Object object) { return new MybatisMapWrapper(metaObject, (Map) object); } }
在官方文档中居然没有介绍ObjectWrapperFactory,并且你在mybatis-config.xml中配置时也会提示:The content of element type “objectWrapperFactory” must match “EMPTY”.
七、ReflectorFactory - 反射工厂
反射工厂,用于生成目标类型的Reflector对象,用于属性名称与set/get方法的轻松映射。存在一个默认的实现:
public class DefaultReflectorFactory implements ReflectorFactory { private boolean classCacheEnabled = true; private final ConcurrentMap, Reflector> reflectorMap = new ConcurrentHashMap<>(); public DefaultReflectorFactory() { } @Override public boolean isClassCacheEnabled() { return classCacheEnabled; } @Override public void setClassCacheEnabled(boolean classCacheEnabled) { this.classCacheEnabled = classCacheEnabled; } @Override public Reflector findForClass(Class> type) { if (classCacheEnabled) { // 允许缓存 // 生产入参type的反射器对象,并放入缓存 return reflectorMap.computeIfAbsent(type, Reflector::new); } else { return new Reflector(type); } } }
在官方文档中关于配置文件这一块也没有介绍ReflectorFactory,并且你在mybatis-config.xml中配置时也会提示:The content of element type “reflectorFactory” must match “EMPTY”.
八、plugin - 插件
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。MyBatis支持四种拦截:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)ParameterHandler (getParameterObject, setParameters)ResultSetHandler (handleResultSets, handleOutputParameters)StatementHandler (prepare, parameterize, batch, update, query)
其中Executor 表示拦截的类,括号里面的为类里面被拦截的方法(比如Executor 类里面的query方法、ParameterHandler类的getParameterObject方法)。注意的是,不管多么复杂的 *** 作最后都是基于Executor中的方法,因此最后总会执行Executor里面的方法。
@Signature属性介绍:
type: 表示要拦截的类的class对象 - Executor、 ParameterHandler 、ResultSetHandler 、StatementHandler method: 表示要拦截的方法 - 参考上面 args: 方法的参数的class对象
示例:
显示sql执行了多少毫秒|秒|分钟,当然此处的示例的编写方式可能不恰当,但仅仅只是作为一个简单的示例来说明其用法:
@Intercepts( @Signature(type = Executor.class,method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) ) public class SqlRunTimeInterceptor implements Interceptor { private Properties properties; @Override public Object intercept(Invocation invocation) throws Throwable { String timeUnit = properties.getProperty("timeUnit","millis"); long start = System.currentTimeMillis(); MappedStatement arg = (MappedStatement) invocation.getArgs()[0]; String methodUrl = arg.getId(); Object target = invocation.proceed(); long end = System.currentTimeMillis(); double runTime = end - start; if (timeUnit.equals("sec")) { runTime = runTime / 1000; } if (timeUnit.equals("min")) { runTime = runTime / 1000 / 60; } System.out.println(methodUrl + "方法: 执行时间为" + runTime + " " + timeUnit); return target; } @Override public Object plugin(Object target) { return Plugin.wrap(target,this); } @Override public void setProperties(Properties properties) { this.properties = properties; } }
结果: com.bihai.mybatis_study.mapper.PhoneMapper.selectAll方法: 执行时间为0.319 sec
Interceptor接口:
// 拦截器 Invocation:调用 // 这是插件接口,所有插件需要实现该接口 public interface Interceptor { Object intercept(Invocation invocation) throws Throwable; default Object plugin(Object target) { return Plugin.wrap(target, this); } default void setProperties(Properties properties) { // NOP } }
九、environments - 环境
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
每个环境对应着一个SqlSessionFactory,如果没有指定则加载默认的环境:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
配置:
。。。 。。。。
说明: 1、默认环境
....
默认的环境,在加载时没有指定环境则使用该环境。
2、环境id
....
用于指定environment的环境id,该id的名称可以随意,没有限制,可以作为参数传给SqlSessionFactoryBuilder的build方法,来创建一个该环境的SqlSession。
3、事务管理器
type的值可以是:JDBC | MANAGED,这两种事务管理器类型都不需要设置任何属性。它们其实是类型别名,自己也可以自定义事务管理器
JDBC:这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
MANAGED:它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。
默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。(比如Spring与MyBatis的整合,但你无需做什么配置,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。)
自定义对MyBais事务的管理:
TransactionFactory 、Transaction
4、数据源。。。
type属性用于指定以什么方式创建数据源,可以分为三类:POOLED | UNPOOLED| JNDI,同样的这三个也是类型别名,这意味着可以自定义使用像Druid等数据库连接池来进行池化连接,这就显得很有意义。
UNPOOLED的属性:
这个数据源的实现会每次请求时打开和关闭连接。以下是可配置的属性:
driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。url – 这是数据库的 JDBC URL 地址。username – 登录数据库的用户名。password – 登录数据库的密码。defaultTransactionIsolationLevel – 默认的连接事务隔离级别。defaultNetworkTimeout – 等待数据库 *** 作完成的默认网络超时时间(单位:毫秒)。driver.xxx - 传递个属性给数据库驱动(比如:driver.encoding=UTF8,将通过 DriverManager.getConnection(url, driverProperties) 方法传递值为 UTF8 的 encoding 属性给数据库驱动。)
POOLED的属性:
加入池化的概念,避免了频繁的创建关闭连接,一下是可配置的属性:
poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnections 与 poolMaximumLocalBadConnectionTolerance 之和。 默认值:3(新增于 3.4.5)poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
注意:对于type值为POOLED的数据源来说,UNPOOLED的属性也可以使用,因为其对应的类为父子类的关系。
JNDI的属性:
为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。这种数据源配置只需要两个属性:
initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。
data_source – 这是引用数据源实例位置的上下文路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
env.xxx=xxx - ( 比如:env.encoding=UTF8,这就会在 InitialContext 实例化时往它的构造方法传递值为 UTF8 的 encoding 属性。)
示例:
1、在Tomcat的context.xml文件中配置数据源参数
WEB-INF/web.xml
2、mybatis-config.xml配置
3、为了避免部署到websphere中lookup报错,在web.xml中加入resource引用
jdbc/testDs javax.sql.DataSource Container
Druid作为数据源:
整合第三方数据源,需要实现DataSourceFactory或者继承他的两个实现类UnPooledDataSourceFactory或PooledDataSourceFactory。
public interface DataSourceFactory { //设置数据源属性,参数为一个Properties对象,xml解析后的参数会被传入 void setProperties(Properties props); //获取数据源 DataSource getDataSource(); }
1、创建DataSourceFactory实现类,使用Druid
public class DruidDataSourceFactory implements DataSourceFactory{ private Properties properties; @Override public DataSource getDataSource() { //创建druid数据源,这是druid jar包提供的一个类 DruidDataSource ds = new DruidDataSource(); //从配置好的properties加载配置 ds.setUsername(this.properties.getProperty("username"));//用户名 ds.setPassword(this.properties.getProperty("password"));//密码 ds.setUrl(this.properties.getProperty("url")); ds.setDriverClassName(this.properties.getProperty("driverClassName")); ds.setInitialSize(this.properties.getProperty("initialSize"));//初始连接数 ds.setMaxActive(this.properties.getProperty("maxActive"));//最大活动连接数 ds.setMaxWait(this.properties.getProperty("maxWait"));//最大等待时间 da.setMinIdle(this.properties.getProperty("minIdle")); //初始化连接 try { ds.init(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ds; } @Override public void setProperties(Properties properties) { // xml文档会将properties注入进来 this.properties=properties; } }
2、配置mybatis-config.xml
路径
十、databaseIdProvider - 数据库厂商标识
MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。MyBatis 会加载带有匹配当前数据库 databaseId 属性和所有不带 databaseId 属性的语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。
比如:会选择第一个,因为它设置databaseId,且正好匹配mysql
select * from phone;
格式说明:
此次type支持的类型只支持一种:DB_VENDOR,没错它又是别名,这也意味着可以扩展,具体的接口为org.apache.ibatis.mapping.DatabaseIdProvider,DB_VENDOR对应的类实现了该接口。
该实现会将 databaseId 设置为 DatabasemetaData#getDatabaseProductName() 返回的字符串。
同时由于返回的字符串可能太长了,因此可以通过
示例:
1、配置mybatis-config.xml
2、指定sql语句的databaseIdProvider
3、结果
Phone(id=00001, phone=13467326809, type=移动)
我的情况是连接的是MySQL数据库,此时databaseId为mysqlId 与 没有设置databaseId的语句会被加载,但也由于两个语句相同,因此不带databaseId的sql语句会被抛弃。此时执行的结果即为第一条语句的执行结果。
十一、mappers - 映射器
用于扫描对应的映射文件的位置,此配置是很重要
支持四种方式:
1、
2、
3、
4、
注意:3、4这种情况需要映射接口与映射文件保持相同的路径,且类名与文件名相同
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)