这些属性都是可外部配置且可动态替换的,既能够在典型的 Java 属性文件中配置,亦可经过 properties 元素的子元素来传递。例如:java
<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" />
其中的属性就能够在整个配置文件中使用来替换须要动态配置的属性值。好比:mysql
<property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/>
如何配?面试
在config.xml 文件中\<configuration>引入子标签spring
<properties resource="jdbc.properties"></properties>
并修改原有数据源链接相关配置以下:sql
<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>
便可完成。数据库
这是MyBatis 修改操做运行过程细节的重要的步骤。下方这个表格描述了这些设置项、含义和默认值。通常咱们用默认便可(详细解释见官网文档)apache
对应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>
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减小类彻底限定名的冗余。例如:session
Configuration 标签下添加mybatis
<typeAliases> <typeAlias alias="customer" type="com.xxx.pojo.Customer" /> </typeAliases>
修改CustomerMapper.xml 文件
<!-- 查询客户--> <select id="queryCustomerById" parameterType="int" resultType="customer"> SELECT id,user_name 'userName' FROM yg_customer WHERE id=#{id} </select>
也能够指定一个包名(你们最喜欢的方式),MyBatis 会在包名下面搜索须要的 Java Bean,好比:
<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 |
不管是 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 类型。
MyBatis 每次建立结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。默认的对象工厂须要作的仅仅是实例化目标类,要么经过默认构造方法,要么在参数映射存在的时候经过参数构造方法来实例化。默认状况下,咱们不须要配置,mybatis会调用默认实现的objectFactory。从这个类的外部看,这个类的主要做用就是根据一个类的类型获得该类的一个实体对象,好比,咱们给他一个User的type,他将会给咱们一个Tiger的实体对象,咱们给他一个java.lang.List对象,他将会给咱们一个List的实体对象。相似于spring 工厂实例化bean
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 接口,并指定了想要拦截的方法签名便可。
总配置添加
<!-- 插件 --> <plugins> <plugin interceptor="com.xxx.plugins.ExamplePlugin"> <property name="someProperty" value="100" /> </plugin> </plugins>
插件demo:
@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")); } }
MyBatis 能够配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实状况下有多种理由须要这么作。例如,开发、测试和生产环境须要有不一样的配置;或者共享相同 Schema 的多个生产数据库, 想使用相同的 SQL 映射。许多相似的用例。
不过要记住:尽管能够配置多个环境,每一个 SqlSessionFactory 实例只能选择其一。
因此,若是你想链接两个数据库,就须要建立两个 SqlSessionFactory 实例,每一个数据库对应一个。而若是是三个数据库,就须要三个实例,依此类推,记起来很简单:
· 每一个数据库对应一个 SqlSessionFactory 实例
<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>
## 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
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(); } }
在 MyBatis 中有两种类型的事务管理器(也就type=”[JDBC|MANAGED]”):
<transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager>
若是你正在使用 Spring + MyBatis,则没有必要配置事务管理器, 由于 Spring 模块会使用自带的管理器来覆盖前面的配置。(集成时会讲到)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 链接对象的资源。
数据源类型有三种:UNPOOLED,POOLED,JNDI
UNPOOLED
这个数据源的实现只是每次被请求时打开和关闭链接。虽然有一点慢,它对在及时可用链接方面没有性能要求的简单应用程序是一个很好的选择。 不一样的数据库在这方面表现也是不同的,因此对某些数据库来讲使用链接池并不重要,这个配置也是理想的。
做为可选项,你也能够传递属性给数据库驱动。要这样作,属性的前缀为“driver.”,例如:
这将经过DriverManager.getConnection(url,driverProperties)方法传递值为 UTF8 的 encoding 属性给数据库驱动。
POOLED
这种数据源的实现利用“池”的概念将 JDBC 链接对象组织起来,避免了建立新的链接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。(通常选用这种)
JNDI
这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器能够集中或在外部配置数据源,而后放置一个 JNDI 上下文的引用。
这就会在初始上下文(InitialContext)实例化时往它的构造方法传递值为 UTF8 的 encoding 属性。
这里是告诉mybatis去哪寻找映射SQL 的语句。可使用类路径中的资源引用,或者使用字符,输入确切的URL 引用。
!— 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 映射文件。
接口定义:
public interface CustomerDao { Customer queryCustomerByName(String userName); }
<?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>
<mappers> <!-- <mapper resource="com/xxx/mapper/CustomerDao.xml" />--> <package name="com.xxx.dao"/> </mappers>
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(); } }