此博客用于个人学习,来源于ssm框架的书籍,对知识点进行一个整理。
2.1 概述:
MyBatis 的各项配置项中,properties,settings,typeAliases,typeHandler,plugin,environments,mappers 是常用的内容,其中的顺序如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!--配置-->
<properties/><!--属性-->
<settings/><!--设置-->
<typeAliases/><!--类型命名-->
<typeHandler/><!--类型处理器-->
<plugins/><!--插件-->
<environments><!--配置环境-->
<environment><!--环境变量-->
<transactionManager/><!--事务管理器-->
<dataSource/><!--数据源-->
</environment>
</environments>
<mapper/><!--映射器-->
</configuration>
需要注意的是,MyBatis 配置项的顺序不能颠倒,如果发生了颠倒,就会产生异常,导致程序无法运行。
2.2 properties 属性:
properties 属性可以给系统配置一些运行参数,可以放在 XML 文件或者是 properties 文件中,而不是放在 Java 编码中,这样的好处是在于方便参数修改,而不会引起代码的重新编译。MyBatis 中提供了 3 种方式让我们使用 properties ,它们是:
- property 子元素
- properties 文件
- 程序代码传递
其中,除非是对数据库的用户与密码进行解密,不然一般考虑使用前两种,于是只对前两种进行展开。
2.2.1 property 子元素:
使用 property 子元素将数据库连接的相关配置进行改写,如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis的主配置文件-->
<configuration>
<properties>
<property name="database.driver" value="com.mysql.jdbc.Driver"/>
<property name="database.url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="database.username" value="root"/>
<property name="database.password" value="root"/>
</properties>
<typeAliases><!--别名-->
<typeAlias alias="role" type="com.itheima.dao.pojo.Role"/>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接源(连接池)-->
<dataSource type="POOLED">
<!--配置数据库的四个信息-->
<property name="driver" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</dataSource>
</environment>
</environments>
<!-- 告知 mybatis 映射配置的位置 -->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"/>
</mappers>
</configuration>
这样的好处是定义一次后可以到处引用了,但是如果属性参数有成百上千个,这个时候应该使用 properties 文件的方式。
2.2.2 使用 properties 文件:
使用 properties 文件是比较普遍的方法,我们可以配置多个键值放在一个 properties 文件中,也可以把多个键值放在多个 properties 文件中,方便日后维护和修改。
jdbc.properties 文件放到 classpath 的路径下,代码为:
database.driver=com.mysql.jdbc.Driver
database,url=jdbc:mysql://localhost:3306/ssm
database.username=root
database.password=root
在 MyBatis 中通过 <properties> 的属性 resource 来引入 properties 文件。
<properties resource="jdbc.properties"/>
这个时候通过维护 properties 文件可以维护我们的配置内容。
2.2.3 总结:
这三种方式是有优先级的,最优先的是使用程序传递的方式,其次是使用 properties 文件的方式,最后是使用 property 子元素的方式,MyBatis 会根据优先级来覆盖原先配置的属性值。
2.3 settings 配置:
settings 的配置项很多,但是真正用到的不会太多,我们把常用的配置项研究清楚就可以了,比如关于缓存的 cacheEnabled,关于级联的 lazyLoadingEnabled 和 aggressiveLazy Loading,关于自动映射的 autoMappingBehavior 和 mapUnderscoreToCamelCase,关于执行器类型的 defaultExecutorType 等。
2.4 typeAliases 别名:
由于类的全限定名称很长,需要大量使用的时候,总写那么长的名称不方便。在 MyBatis 中允许定义一个简写来代表这个类,这就是别名,别名分为系统定义别名和自定义别名。在 MyBatis 中别名由类 TypeAliasRegistry 去定义。注意,在 MyBatis 中别名不区分大小写。
2.4.1 系统定义别名:
在 MyBatis 中,系统自动初始化了一些别名。我们在使用的时候,不要重复命名,导致出现其他问题。
2.4.2 自定义别名:
由于在大型互联网系统中存在许多对象,比如用户(User)这个对象有时需要大量重复地重复使用,因此 MyBatis 也提供了用户自定义别名的规则。我们可以采用配置文件或者扫描方式来自定义它。
<typeAliases><!--别名-->
<typeAlias alias="role" type="com.itheima.dao.pojo.Role"/>
<typeAlias alias="user" type="com.itheima.dao.pojo.Role"/>
</typeAliases>
这样就可以定义一个别名了,但如果这个时候有许多类需要定义别名,使用配置的方式就不轻松了。拿上面两个举例,Role 和 User 在都在 com.itheima.dao.pojo 这个包下,我们可以通过包扫描别名。
<typeAliases><!--别名-->
<package name="com.itheima.dao.pojo"/>
</typeAliases>
MyBatis 通过扫描这个包,将里面的类的第一个字母变成小写作为别名。但这个时候容易出现重命名错误,比如先在 typeAlias 中配置了 Role 这个类,然后再对 pojo 这个包进行扫描,就会由于重命名而出现异常,这个时候可以使用注解进行解决。
@Alias("role3")
public class Role{
...
}
2.5 ObjectFactory(对象工厂):
当创建结果集的时候,MyBatis 会使用一个对象工厂来完成创建这个结果集实例。默认情况下,MyBatis 会使用其定义的对象工厂—— DefaultObjectFactory 来完成对应的工作。同样的,允许自定义,则需要实现接口 ObjectFactory ,并给予配置。
public class MyObjectFactory extends DefaultObjectFactory {
private static final long serialVersionUID = -8855122346740914948L;
Logger log = Logger.getLogger(String.valueOf(MyObjectFactory.class));
private Object temp = null;
@Override
public void setProperties(Properties properties) {
super.setProperties(properties);
log.info("初始化参数:【"+properties.toString()+"】");
}
//方法二
@Override
public <T> T create(Class<T> type) {
T result = super.create(type);
log.info("创建对象:"+result.toString());
log.info("是否和上次创建的是同一个对象:【"+(temp == result)+"】");
return result;
}
//方法一
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
T result = super.create(type, constructorArgTypes, constructorArgs);
log.info("创建对象:"+result.toString());
temp = result;
return result;
}
@Override
public <T> boolean isCollection(Class<T> type) {
return super.isCollection(type);
}
}
然后对其进行配置:
<objectFactory type="com.itheima.objectFactory.MyObjectFactory">
<property name="prop1" value="value1"/>
</objectFactory>
采用的配置的 MyObjectFactory 来生成结果集对象:
sqlSession = MyBatisUtil.getSqlSession();
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
Role role = roleMapper.getRole(1L);
System.out.println(role.getRoleName());
最后会发现,MyBatis 创建了一个 List 对象和一个 Role 对象,它会先调用方法1,然后调用方法2,最后只是生成了同一个对象,使用在写入的判断中,始终返回的是 true。因为返回的是一个 Role 对象,所以它会最后适配一个 Role 对象,这就是它的工作过程。
2.6 environment(运行环境):
运行环境的主要作用是配置数据库信息,它可以配置多个数据库,一般只需要配置一个。它下面分为两个可配置的元素:事务管理器(transactionManager),数据源(dataSource)。
2.6.1 transactionManager(事务管理器):
在 MyBatis 中,transactionManager 提供了两个实现类,它需要实现接口 Transaction,从方法可知,它主要的工作是提交(commit),回滚(rollback)和关闭(close)数据库的事务。事务管理器有下面两种方式:
<transactionManager type="JDBC"/>
<transactionManager type="MANAGED"/>
做简要的说明:
- JDBC 使用的是 JdbcTransactionFactory 生成的 JdbcTransaction 对象实现,它是以 JDBC 的方式对数据库的提交和回滚进行操作。
- MANAGED 使用 ManagedTransactionFactory 生成的 ManagedTransaction 对象实现。它的提交和回滚方法不用任何操作,而是把事务交给容器处理。
2.6.2 environment 数据源环境:
environment 的主要作用是配置数据库,存在三种数据源,我们可以这样进行配置:
<dataSource type="UNPOOLED">
<dataSource type="POOLED">
<dataSource type="JNDI">
- UNPOOLED:
采用非数据池的管理方式,每次请求就会打开一个新的数据库连接,所以创建会比较慢,可以配置以下属性:driver(数据库驱动名),url(连接数据库的URL),username(用户名),password(密码),defaultTransactionIsolationLevel(默认的连接事务隔离级别)。 - POOLED:
利用数据池的管理方式,所以请求时,无须再建立和验证,省去了创建新的连接实例时所必需的初始化和认证时间。 - JNDI:
数据源 JNDI 的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
2.7 引入映射器的方法:
映射器对应命名空间(namespace)的方法,命名空间对应的是一个接口的全路径,而不是实现类。首先,定义接口:
public interface RoleMapper{
public Role getRole(Long id);
}
其次,给出 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.itheima.dao.pojo.role.RoleMapper">
<!--配置查询所有操作-->
<select id="findAll" resultType="com.itheima.domain.Role">
select * from t_role;
</select>
</mapper>
引入映射器的方法有四个:
-
用文件路径引入映射器:
<mappers> <mapper resource="com/itheima/mapper/roleMapper.xml"/> </mappers>
-
用包名映入映射器:
<mappers> <package name="com.itheima.mapper"/> </mappers>
-
用类注册引入映射器:
<mappers> <mapper class="com.itheima.mapper.RoleMapper"/> <mapper class="com.itheima.mapper.UserMapper"/> </mappers>
-
用 useMapper.xml 引入映射器:
<mappers> <mapper url="file:///com/itheima/mapper/roleMapper.xml"/> </mappers>