可以扩展和修改
<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里定义了
参数 > 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>这样子符号就从:变为?:
用来当作昵称 只作用于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.xmlmapper也可以直接用User这个type了 也可以直接把一个包放到typeAliases中
<typeAliases> <package name="domain.blog"/> </typeAliases>这样子domain.blog包下的所有Java class文件都可以直接用了 其中的文件的alias有默认值,为小写 也可以这样子自定义:
@Alias("author") public class Author { ... }有各种typehandler 也可以自定义 自定义只要实现org.apache.ibatis.type.TypeHandler接口,或继承org.apache.ibatis.type.BaseTypeHandler类 然后在configuration中加上
<!-- mybatis-config.xml --> <typeHandlers> <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers>与typeAliases一样,也可以放个packagetag在里面
每当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>可以用来拦截调用,默认可以拦截这些调用:
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>mybatis可以有很多个environments,每一个代表一个database,当Development,Test,Production不同情况下不同的数据库,或者多个数据库连在一起的大型数据库 一个sqlSessionFactory只能有一个environment
如果不传入environment,那么就会传入默认的:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);主要的结构有:
environments中默认的environment id (default = development)每个environment的id (id=development)TransactionManager的设置(type=jdbc)DataSource的设置(type=pooled)一共有两种 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; }内置三种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>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了,有多种路径方法可以添加:
classpath 相对路径全路径class namepackage 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>