一、environments配置信息:
environments的作用是用来配置数据库信息,可以配置多个,其有两个可配的子元素,分别是:事务管理器transactionManager和数据源dataSource,先看一下我配置的例子:
1 <!-- 环境模式:development开发模式 work工作模式 --> 2 <environments default="development"> 3 <!--环境变量 --> 4 <environment id="development"> 5 <!--事务管理器 --> 6 <transactionManager type="JDBC" /> 7 <!--数据源 --> 8 <dataSource type="POOLED"> 9 <property name="driver" value="${db.driver}" /> 10 <property name="url" value="${db.url}" /> 11 <property name="username" value="${db.username}" /> 12 <property name="password" value="${db.pwd}" /> 13 </dataSource> 14 </environment> 15 </environments>
配置项说明:
1⃣️environments-default:该属性指定当前的环境,有development和work两种选择,默认是development开发模式;
2⃣️environment-id:该属性是每个environment定义的环境,也有development和work两种选择,默认是development开发模式;
3⃣️transactionManager-type:该属性是配置事务管理器的类型,mybatis中有JDBC和MANAGED两种,一次只能配置一个,后面会介绍;
4⃣️dataSource-type:该属性用来配置数据源类型,有UNPOOLED、POOLED和JNDI三种选择,后面会介绍;
5⃣️dataSource中的property元素就是数据库相关的信息
注意:environment可以配置多个,但是如果同一种模式,如development模式,配置了两个环境environment,mybatis会用后面的覆盖前面的,如下配置:
1 <environments default="development"> 2 <!--环境变量 --> 3 <environment id="development"> 4 <!--事务管理器 --> 5 <transactionManager type="MANAGED" /> 6 <!--数据源 --> 7 <dataSource type="POOLED"> 8 <property name="driver" value="${db.driver}" /> 9 <property name="url" value="${db.url}" /> 10 <property name="username" value="${db.username}" /> 11 <property name="password" value="${db.pwd}" /> 12 </dataSource> 13 </environment> 14 <!--环境变量 --> 15 <environment id="development"> 16 <!--事务管理器 --> 17 <transactionManager type="JDBC" /> 18 <!--数据源 --> 19 <dataSource type="POOLED"> 20 <property name="driver" value="${db.driver}" /> 21 <property name="url" value="${db.url}" /> 22 <property name="username" value="${db.username}" /> 23 <property name="password" value="${db.pwd}" /> 24 </dataSource> 25 </environment> 26 </environments>
上面的例子中我配了两个environment,但是它们的环境模式都是开发模式,此时在开发环境中生效的是后面的,即事务管理器为JDBC的配置,所以一般多个最多配置两个环境,且开发模式不同,一个是开发环境,一个是工作环境。下面通过代码获取环境配置信息:
1 /** 2 * 获取环境信息 3 */ 4 public static void getEnvironment() { 5 SqlSession sqlSession = getSqlSession(); 6 Environment env = sqlSession.getConfiguration().getEnvironment(); 7 TransactionFactory tf = env.getTransactionFactory(); 8 System.out.println(tf.getClass().getSimpleName()); 9 }
输出结果:
1 JdbcTransactionFactory
可以看到返回的事务管理器类型为JdbcTransactionFactory,而当我在配置中把事务管理器改成MANAGED时,会获取到ManagedTransactionFactory类型。下面分开介绍事务管理器和数据源的配置内容。
二、transactionManager事务管理器配置
在MyBatis中,transactionManager提供了两个实现类,都需要实现接口Transaction,我们可以查看以下它的源代码:
1 public interface Transaction { 2 3 4 Connection getConnection() throws SQLException; 5 6 void commit() throws SQLException; 7 8 void rollback() throws SQLException; 9 10 void close() throws SQLException; 11 12 Integer getTimeout() throws SQLException; 13 14 }
从提供的方法中可以知道,它主要完成提交、回滚、关闭数据库的事务。MyBatis中为Transaction接口提供了两个实现类,分别是JdbcTransaction和ManagedTransaction,并且分别对应着JdbcTransactionFactory和ManagedTransactionFactory两个工厂,这两个工厂实现了TransactionFactory这个接口,当我们在配置文件中通过transactionManager的type属性配置事务管理器类型的时候,mybatis就会自动从对应的工厂获取实例。下面说一下这两者的区别:
1⃣️JDBC使用JdbcTransactionFactory工厂生成的JdbcTransaction对象实现,以JDBC的方式进行数据库的提交、回滚等操作;
2⃣️MANAGED使用ManagedTransactionFactory工厂生成的ManagedTransaction对象实现,它的提交和回滚不需要任何操作,而是把事务交给容器进行处理,默认情况下会关闭连接,如果不希望默认关闭,只要将其中的closeConnection属性设置为false即可。
我在测试的过程中发现的最明显的区别就是,如果我使用JDBC的事务处理方式,当我向数据库中插入一条数据时,在调用完插入接口执行SQL之后,必须 执行sqlSession.commit();进行提交,否则虽然插入成功但是数据库中还是看不到刚才插入的数据;而使用MANAGED方式就不一样了,只需调用接口即可,无需手动提交。
当然,除了使用默认的,我们还可以根据需要自定义一个事务管理器,需要以下三步:
第一步:创建一个事务管理类,继承ManagedTransaction或JdbcTransaction类或实现Transaction接口;
1 /** 2 * 定义自己的事务管理器 3 */ 4 public class MyTransaction extends JdbcTransaction implements Transaction { 5 6 // 重写父类方法 7 public MyTransaction(Connection connection) { 8 super(connection); 9 } 10 11 public MyTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) { 12 super(ds, desiredLevel, desiredAutoCommit); 13 } 14 }
第二步:创建一个事务管理工厂类,实现TransactionFactory接口,提供生产事务处理相关接口;
1 /** 2 * 定义自己的事务管理器,实现获取连接、提交、回滚、关闭数据库连接等操作 3 */ 4 public class MyTransaction extends JdbcTransaction implements Transaction { 5 6 public MyTransaction(Connection connection) { 7 super(connection); 8 } 9 10 public MyTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) { 11 super(ds, desiredLevel, desiredAutoCommit); 12 } 13 14 @Override 15 public Connection getConnection() throws SQLException { 16 return super.getConnection(); 17 } 18 19 @Override 20 public void commit() throws SQLException { 21 super.commit(); 22 } 23 24 @Override 25 public void rollback() throws SQLException { 26 super.rollback(); 27 } 28 29 @Override 30 public void close() throws SQLException { 31 super.close(); 32 } 33 34 @Override 35 public Integer getTimeout() throws SQLException { 36 return super.getTimeout(); 37 } 38 }
第三步:配置自定义事务管理器
1 <transactionManager type="com.daily.objectfactory.MyTransactionFactory" />
注意⚠️:这个地方配置的是自定义的工厂类,而不是事务管理类,因为mybatis是根据配置的工厂获取具体实例对象的。
要不是亲手实践,差点就忽略了这点呢!!!
通过以上三步就完成了自定义事务管理器的配置,其实我们还可以在别名设置这个工厂的别名,然后在此处引用,如下:
先在别名中配置工厂所在的包
1 <typeAliases> 2 <!-- 对包进行扫描,可以批量进行别名设置,设置规则是:获取类名称,将其第一个字母变为小写 --> 3 <package name="com.daily.objectfactory" /> 4 </typeAliases>
然后按照规则,该包下所有类的别名是将类的第一个字母变成小写,所以我自定义的这个事务管理器工厂MyTransactionFactory的别名就是myTransactionFactory,这样我就可以在事务管理配置中使用该别名了,如下:
1 <!--事务管理器 --> 2 <transactionManager type="myTransactionFactory" />
三、dataSource数据源配置
在mybatis中,数据库是通过PooledDataSourceFactory、UnpooledDataSourceFactory和JndiDataSourceFactory三个工厂类来提供,前两者分别产生PooledDataSource和UnpooledDataSource类对象,第三个则会根据JNDI的信息拿到外部容器实现的数据库连接对象,但是不管怎样,它们最后都会生成一个实现了DataSource接口的数据库连接对象。
它们的配置信息如下:
1 <dataSource type="POOLED"> 2 <dataSource type="UNPOOLED"> 3 <dataSource type="JNDI">
这三种数据源的意义如下:
1⃣️UNPOOLED
采用非数据库池的管理方式,每次请求都会新建一个连接,所以性能不是很高,使用这种数据源的时候,我们可以配置以下属性:
driver数据库驱动名
url数据库连接URL
username用户名
password密码
defaultTransactionIsolationLevel默认的事务隔离级别,如果要传递属性给驱动,则属性的前缀为driver
2⃣️POOLED
采用连接池的概念将数据库链接对象Connection组织起来,可以在初始化时创建多个连接,使用时直接从连接池获取,避免了重复创建连接所需的初始化和认证时间,从而提升了效率,所以这种方式比较适合对性能要求高的应用中。除了UNPOOLED中的配置属性之外,还有下面几个针对池子的配置:
poolMaximumActiveConnections:任意时间都会存在的连接数,默认值为10
poolMaxmumIdleConnections:可以空闲存在的连接数
poolMaxmumCheckoutTime:在被强制返回之前,检查出存在空闲连接的等待时间。即如果有20个连接,只有一个空闲,在这个空闲连接被找到之前的等待时间就用这个属性配置。
poolTimeToWait:等待一个数据库连接成功所需的时间,如果超出这个时间则尝试重新连接。
还有其他的一些配置,不详述了。
3⃣️JNDI
数据源JNDI的实现是为了能在如EJB或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。这种数据源只需配置两个属性:
initial_context:用来在InitialContext中寻找上下文。可选,如果忽略,data_source属性将会直接从InitialContext中寻找;
data_source:引用数据源实例位置上下文的路径。当提供initial_context配置时,data_source会在其返回的上下文进行查找,否则直接从InitialContext中查找。
除了上述三种数据源之外,mybatis还提供第三方数据源,如DBCP,但是需要我们自定义数据源工厂并进行配置,这一点暂时不做研究。
以上就是environments运行环境的配置。