# Mybatis配置文件如何进行配置呢?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-As1L3kZG-1602464876198)(https://imgkr.cn-bj.ufileos.com/768074eb-5e03-4ad1-81ee-5432b6614e4a.jpg)]
## Mybatis配置文件配置的方式
- properties
- settings
- typeAliases
- typeHandlers
- objectFactory
- plugins
- environments
- transactionManager
- dataSource
- mappers
## 案例实操
### 1. properties
这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。例如:
~~~ xml
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
~~~
其中的属性就可以在整个配置文件中使用来替换需要动态配置的属性值。比如:
~~~ xml
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
~~~
如何配?
在config.xml 文件中\<configuration>引入子标签
~~~ xml
<properties resource="jdbc.properties"></properties>
~~~
并修改原有数据源连接相关配置如下:
~~~ xml
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
~~~
即可完成。
### **2.** **settings**(了解)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Onyfk3D-1602464876203)(https://imgkr.cn-bj.ufileos.com/d0372a13-d467-4f73-a99b-45dfa35973b2.png)]
这是MyBatis 修改操作运行过程细节的重要的步骤。下方这个表格描述了这些设置项、含义和默认值。一般我们用默认即可(详细解释见官网文档)
对应xml配置如下(开发中一般采用默认配置即可):
~~~ xml
<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="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<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>
~~~
### **3.**typeAliases
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如:
Configuration 标签下添加
~~~ xml
<typeAliases>
<typeAlias alias="customer" type="com.xxx.pojo.Customer" />
</typeAliases>
~~~
修改CustomerMapper.xml 文件
~~~ xml
<!-- 查询客户-->
<select id="queryCustomerById" parameterType="int" resultType="customer">
SELECT id,user_name 'userName' FROM yg_customer WHERE id=#{id}
</select>
~~~
也可以指定一个包名(**大家最喜欢的方式**),MyBatis 会在包名下面搜索需要的 Java Bean,比如:
~~~ xml
<typeAliases>
<!-- <typeAlias alias="customer" type="com.xxx.pojo" /> -->
<package name="com.xxx.pojo"/>
</typeAliases>
~~~
每一个在包**com.xxx.pojo** 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如com.xxx.pojo.Customer 的别名为customer ;
若有注解,则别名为其注解值。 注解名@Alias(value=“user”)
同样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 |
| object | Object |
| map | Map |
| hashmap | HashMap |
| list | List |
| arraylist | ArrayList |
| collection | Collection |
| iterator | Iterator |
### 4.typeHandlers 类型处理器(面试有可能会问)
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
| BooleanTypeHandler | java.lang.Boolean, boolean | 数据库兼容的 BOOLEAN |
| -------------------------- | -------------------------- | ------------------------------------------------------------ |
| ByteTypeHandler | java.lang.Byte, byte | 数据库兼容的 NUMERIC 或 BYTE |
| ShortTypeHandler | java.lang.Short, short | 数据库兼容的 NUMERIC 或 SHORT INTEGER |
| IntegerTypeHandler | java.lang.Integer, int | 数据库兼容的 NUMERIC 或 INTEGER |
| LongTypeHandler | java.lang.Long, long | 数据库兼容的 NUMERIC 或 LONG INTEGER |
| FloatTypeHandler | java.lang.Float, float | 数据库兼容的 NUMERIC 或 FLOAT |
| DoubleTypeHandler | java.lang.Double, double | 数据库兼容的 NUMERIC 或 DOUBLE |
| BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
| StringTypeHandler | java.lang.String | CHAR, VARCHAR |
| ClobReaderTypeHandler | java.io.Reader | - |
| ClobTypeHandler | java.lang.String | CLOB, LONGVARCHAR |
| NStringTypeHandler | java.lang.String | NVARCHAR, NCHAR |
| NClobTypeHandler | java.lang.String | NCLOB |
| BlobInputStreamTypeHandler | java.io.InputStream | - |
| ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
| BlobTypeHandler | byte[] | BLOB, LONGVARBINARY |
| DateTypeHandler | java.util.Date | TIMESTAMP |
| DateOnlyTypeHandler | java.util.Date | DATE |
| TimeOnlyTypeHandler | java.util.Date | TIME |
| SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
| SqlDateTypeHandler | java.sql.Date | DATE |
| SqlTimeTypeHandler | java.sql.Time | TIME |
| ObjectTypeHandler | Any | OTHER 或未指定类型 |
| EnumTypeHandler | Enumeration Type | VARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引) |
| EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称)。 |
你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个 JDBC 类型。
### **5.** 对象工厂(objectFactory)(了解)
MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。默认情况下,我们不需要配置,mybatis会调用默认实现的objectFactory。从这个类的外部看,这个类的主要作用就是根据一个类的类型得到该类的一个实体对象,比如,我们给他一个User的type,他将会给我们一个Tiger的实体对象,我们给他一个java.lang.List对象,他将会给我们一个List的实体对象。**类似于spring 工厂实例化bean**
### **6. plugins 插件**
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
· Executor (sql执行时, update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
· ParameterHandler (参数的处理, getParameterObject, setParameters)
· ResultSetHandler (结果集的处理, handleResultSets, handleOutputParameters)
· StatementHandler (申明语句的处理, prepare, parameterize, batch, update, query)
这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 的发行包中的源代码。 假设你想做的不仅仅是监控方法的调用,那么你应该很好的了解正在重写的方法的行为。 因为如果在试图修改或重写已有方法的行为的时候,你很可能在破坏 MyBatis 的核心模块。 这些都是更低层的类和方法,所以使用插件的时候要特别当心。
通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定了想要拦截的方法签名即可。
总配置添加
~~~ xml
<!-- 插件 -->
<plugins>
<plugin interceptor="com.xxx.plugins.ExamplePlugin">
<property name="someProperty" value="100" />
</plugin>
</plugins>
~~~
插件demo:
~~~ java
@Intercepts({
@Signature(
type=Executor.class,
/**
* 拦截所有方法
*/
method="query",
/**
* 参数定义
*/
args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class} )
})
public class ExamplePlugin implements Interceptor {
/**
* 每个插件必须实现以下三个方法
*/
/**
* Object intercept(Invocation invocation)是实现拦截逻辑的地方,
* 内部要通过invocation.proceed()显式地推进责任链前进,也就是调用下一个拦截器拦截目标方法。
*/
public Object intercept(Invocation invocation) throws Throwable { System.out.println("intercept");
return invocation.proceed();
}
/**
* Object plugin(Object target) 就是用当前这个拦截器生成对目标target的代理,
* 实际是通过Plugin.wrap(target,this) 来完成的,把目标target和拦截器this传给了包装函数。
*/
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
/**
* setProperties(Properties properties)用于设置额外的参数,参数配置在拦截器的Properties节点里。
*/
public void setProperties(Properties properties) { System.out.println(properties.get("hello"));
}
}
~~~
### 7. 配置环境(environments)(熟悉 配多个数据源)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者共享相同 Schema 的多个生产数据库, 想使用相同的 SQL 映射。许多类似的用例。
**不过要记住:尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一。**
所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:
**·** **每个数据库对应一个 SqlSessionFactory 实例**
~~~ xml
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver2}" />
<property name="url" value="${url2}" />
<property name="username" value="${username2}" />
<property name="password" value="${password2}" />
</dataSource>
</environment>
</environments>
~~~
~~~ xml
## development
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf8
username=root
password=root
## test
driver2=com.mysql.jdbc.Driver
url2=jdbc:mysql://127.0.0.1:3306/mybatis2?useUnicode=true&characterEncoding=utf8
username2=root
password2=root
~~~
测试sqlSessionFactory
~~~ java
public void test02() {
InputStream in;
try {
in = Resources.getResourceAsStream(this.getClass().getClassLoader()
, "config.xml");
// 默认开发库
//SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(in); // 测试库
SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(in,"test");
UserDao userDao=new UserDaoImpl(sqlSessionFactory);
User user= userDao.queryUserById(1);
System.out.println(user);
} catch (IOException e) {
e.printStackTrace();
}
}
~~~
### 8. 事务管理器(transactionManager)(了解)
在 MyBatis 中有两种类型的事务管理器(也就type=”[JDBC|MANAGED]”):
* JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务范围。
* MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
~~~ xml
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
~~~
**如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器, 因为 Spring 模块会使用自带的管理器来覆盖前面的配置。**(集成时会讲到)
### 9.dataSource 数据源(了解)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
数据源类型有三种:UNPOOLED,POOLED,JNDI
**UNPOOLED**
这个数据源的实现只是**每次被请求时打开和关闭连接**。虽然有一点慢,它对在及时可用连接方面没有性能要求的简单应用程序是一个很好的选择。 不同的数据库在这方面表现也是不一样的,所以对某些数据库来说使用连接池并不重要,这个配置也是理想的。
* driver – 这是 JDBC 驱动的 Java 类的完全限定名(并不是JDBC驱动中可能包含的数据源类)。
* url – 这是数据库的 JDBC URL 地址。
* username – 登录数据库的用户名。
* password – 登录数据库的密码。
* defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
作为可选项,你也可以传递属性给数据库驱动。要这样做,属性的前缀为“driver.”,例如:
* driver.encoding=UTF8
这将通过DriverManager.getConnection(url,driverProperties)方法传递值为 UTF8 的 encoding 属性给数据库驱动。
**POOLED**
这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。(一般选用这种)
* poolMaximumActiveConnections – 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10
* poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
* poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
* poolTimeToWait – 这是一个底层设置,如果获取连接花费的相当长的时间,它会给连接池打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。
* poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否处在正常工作秩序中并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。
* poolPingEnabled – 是否启用侦测查询。若开启,也必须使用一个可执行的 SQL 语句设置 poolPingQuery 属性(最好是一个非常快的 SQL),默认值:false。
* poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的使用频度。这可以被设置成匹配具体的数据库连接超时时间,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
**JNDI**
这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
* initial_context – 这个属性用来在 InitialContext 中寻找上下文(即initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么 data_source 属性将会直接从 InitialContext 中寻找。
* data_source – 这是引用数据源实例位置的上下文的路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给初始上下文。比如:
* env.encoding=UTF8
这就会在初始上下文(InitialContext)实例化时往它的构造方法传递值为 UTF8 的 encoding 属性。
### 10.mappers 映射器(四种配置)(熟悉)
这里是告诉mybatis去哪寻找映射SQL 的语句。可以使用类路径中的资源引用,或者使用字符,输入确切的URL 引用。
~~~ xml
!— sqlmapper配置文件路径 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!—url绝对路径形式-->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!—接口 列表配置形式 注解sql-->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!—映射包下所有接口-->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
~~~
这些配置会告诉了 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件。
## 扩展
### 封装Dao
#### 1新建接口CustomerDao
接口定义:
~~~ java
public interface CustomerDao {
Customer queryCustomerByName(String userName);
}
~~~
#### 2 xml映射文件
~~~ xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.dao.CustomerDao">
<!-- 查询客户-->
<select id="queryCustomerByName" parameterType="string" resultType="com.xxx.pojo.Customer">
SELECT id,user_name 'userName',user_balance 'userBalance' FROM yg_customer WHERE user_name=#{userName}
</select>
</mapper>
~~~
#### 3 mappers映射器配置
~~~ xml
<mappers>
<!-- <mapper resource="com/xxx/mapper/CustomerDao.xml" />-->
<package name="com.xxx.dao"/>
</mappers>
~~~
#### 4 测试
~~~ java
public class App
{
public static void main( String[] args ) throws IOException {
//1 加载配置文件
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//2 创建sqlsessionfactor工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//3 构建数据库会话
SqlSession session = factory.openSession();
/* Customer customer = session.selectOne("com.xxx.mapper.customerMapper.queryCustomerById", 2);
System.out.println(customer);*/
CustomerDao customerDao = session.getMapper(CustomerDao.class);
Customer customer = customerDao.queryCustomerByName("zhaoliying");
System.out.println(customer);
session.close();
}
}
~~~
onFactory factory = new SqlSessionFactoryBuilder().build(is);
//3 构建数据库会话
SqlSession session = factory.openSession();
/* Customer customer = session.selectOne("com.xxx.mapper.customerMapper.queryCustomerById", 2);
System.out.println(customer);*/
CustomerDao customerDao = session.getMapper(CustomerDao.class);
Customer customer = customerDao.queryCustomerByName("zhaoliying");
System.out.println(customer);
session.close();
}
}
~~~
需要视频配套文档或更多资料+我们程序员小姐姐v:lezijie007(加好友时备注:b站-LT,不备注拒绝添加哟)