Mybatis-Configuration
properties
可以扩展和修改
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
通过properties标签的resource属性,接收properties文件里的属性
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
这里driver和url,上面没有,在config.properties里,username和password在property里定义了
也可以在创建SqlSessionFactory的时候作为参数传入
SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory =
new SqlSessionFactoryBuilder.build(reader, environment, props);
优先级比较:
参数 > property > resource
默认值设置
要设置默认值先要把默认值开关打开才可以设置:
<properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- Enable this feature -->
</properties>
然后在设置默认值:
<dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${username:ut_user}"/> <!-- If 'username' property not present, username become 'ut_user' -->
</dataSource>
这里username的默认值就是ut_user了
默认值符号
默认为":",但是可能会有冲突
<properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/> <!-- Change default value of separator -->
</properties>
这样子符号就从:
变为?:
typeAliases
用来当作昵称
只作用于xml,在configuration
里设置之后,其他的mapper
也可以使用了
<?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">
<configuration>
<typeAliases>
<typeAlias type="Table.User" alias="User"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/ex3"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="User.xml"/>
</mappers>
</configuration>
这里在configuration
里设置了User
=Tabel.User
,这个configuration
调用的User.xml
mapper也可以直接用User
这个type了
也可以直接把一个包放到typeAliases
中
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
这样子domain.blog
包下的所有Java class文件都可以直接用了
其中的文件的alias有默认值,为小写
也可以这样子自定义:
@Alias("author")
public class Author {
...
}
typeHandler
有各种typehandler
也可以自定义
自定义只要实现org.apache.ibatis.type.TypeHandler
接口,或继承org.apache.ibatis.type.BaseTypeHandler
类
然后在configuration
中加上
<!-- mybatis-config.xml -->
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
与typeAliases
一样,也可以放个package
tag在里面
objectFactory
每当mybatis创建一个result实例的时候,会使用objectFactory
来这么做。默认的objectFactory
会在constructor的基础上多一些小动作。
通过重写可以在创建一个实例的时候多一些自定义的操作
// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
@Override
public <T> T create(Class<T> type) {
return super.create(type);
}
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return super.create(type, constructorArgTypes, constructorArgs);
}
@Override
public void setProperties(Properties properties) {
super.setProperties(properties);
}
@Override
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}}
再在configuration
添加属性
<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
plugins
可以用来拦截调用,默认可以拦截这些调用:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
private Properties properties = new Properties();
@Override
public Object intercept(Invocation invocation) throws Throwable {
// implement pre-processing if needed
Object returnObject = invocation.proceed();
// implement post-processing if needed
return returnObject;
}
@Override
public void setProperties(Properties properties) {
this.properties = properties;
}
}
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
environments
mybatis可以有很多个environments
,每一个代表一个database,当Development,Test,Production不同情况下不同的数据库,或者多个数据库连在一起的大型数据库
一个sqlSessionFactory
只能有一个environment
创建sqlSessionFactory的不同方法
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
如果不传入environment
,那么就会传入默认的:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
environments的结构
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<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>
主要的结构有:
- environments中默认的environment id (default = development)
- 每个environment的id (id=development)
- TransactionManager的设置(type=jdbc)
- DataSource的设置(type=pooled)
transactionManger
一共有两种 type="[JDBC|MANAGED]"
- jdbc:直接使用jdbc的
commit
和rollback
功能,他是根据datasource
接收的connection
来管理会话transaction
的范围的 - managed: 从不
commit
和rollback
,他让container
来管理transaction
,比如(a JEE Application Server context)默认他会关掉connection。但是其他的container就不知道了,如果想要不关闭connection,就设置一下:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
这两个type都不需要properties,但是他们都是type aliases,也就是说,可以放一些自己的TransactionFactory的实现类的全路径
或type alias
public interface TransactionFactory {
default void setProperties(Properties props) { // Since 3.5.2, change to default method
// NOP
}
Transaction newTransaction(Connection conn);
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
xml的properties都会在实例化后传入到setProperties
方法中。
我们也要创建Transaction
实现类:
public interface Transaction {
Connection getConnection() throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
Integer getTimeout() throws SQLException;
}
dataSource
内置三种type type="[UNPOOLED|POOLED|JNDI]"
- unpooled: 每次请求的时候都会打开和关闭connection,这样子会慢。
- pooled: 会积攒连接,每次的创建新
Connection
实例的时候的打开连接和授权操作不用再做了。 - jndi: 这种和container一起使用,如EJB,Application Servers。这些一般会设置
dataSource
,然后把对应的设置引用到jndi中。
我们可以插入任何的第三方dataSource
,要实现以下接口:
org.apache.ibatis.datasource.DataSourceFactory
public interface DataSourceFactory {
void setProperties(Properties props);
DataSource getDataSource();
}
或者继承父类:
org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {
public C3P0DataSourceFactory() {
this.dataSource = new ComboPooledDataSource();
}
}
然后在type里面放入这个类:
<dataSource type="org.myproject.C3P0DataSourceFactory">
<property name="driver" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql:mydb"/>
<property name="username" value="postgres"/>
<property name="password" value="root"/>
</dataSource>
databaseIdProvider
mybatis可以根据不同的数据库供应商来操作,多个数据库供应商的话是根据databaseId
属性的。mybatis会载入所有的没有databaseId
的语句,或者有databaseId
对应的当前的语句。相同的语句,同时有和没有databaseId
的,会选择有的那个,没有的会被忽略。
直接激活多个供应商:
<databaseIdProvider type="DB_VENDOR" />
这样子会返回一些DatabaseMetaData#getDatabaseProductName()
的string,但是这样子的返回的string太长了,可以自己添加property来改写:
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
这样子会只返回property里的,其他的会返回null
。如果DatabaseMetaData#getDatabaseProductName()
返回Oracle (DataDirect
,那么databaseId
就是oracle
。
也可以自定义供应商,实现org.apache.ibatis.mapping.DatabaseIdProvider
接口:
public interface DatabaseIdProvider {
default void setProperties(Properties p) { // Since 3.5.2, changed to default method
// NOP
}
String getDatabaseId(DataSource dataSource) throws SQLException;
}
mappers
现在其他的都设置好了,可以添加mappers
了,有多种路径方法可以添加:
- classpath 相对路径
- 全路径
- class name
- package name
<!-- Using classpath relative resources -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- Using url fully qualified paths -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- Using mapper interface classes -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- Register all interfaces in a package as mappers -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>