包名/类名。
子节点1 : <environments default="development">
(1)事务管理这里用jdbc,还有哪些我们后面补充
<!-- JDBC:自动提交 -->
<transactionManager type="JDBC"></transactionManager> <!-- 事务管理器 -->
(2)数据源先用POOLED方式
<dataSource type="POOLED">
<!-- 数据库的链接参数 --><property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3307/mybatis02" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource><!-- 数据源 -->
子节点2:引入mapper.xml,通过mapper标签的resource属性,mapper.xml由于在source folder中,所以应该用/来连接,包名/类名的格式。
<mappers><!-- 引入mapper。xml -->
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
mark一下,目前在捋老师的每张图片里的属性,以后累了就去写小说,写累了再回来写代码,
我这个人对新鲜的东西特别有热情,但是受不了一直做一样东西。ok,继续回来了。
标签完全参考:http://www.mybatis.org/mybatis-3/zh/configuration.html
子节点3:<properties>标签可以从外部配置文件中导入这些属性,也可以通过<property>子标签来传递属性值进来。
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
子节点4:<settings>控制mybatis运行时行为
子标签<setting name="lazyLoadingEnabled" value="true">
相比于立即加载,延迟加载只有当真正用到对象的内容时才发送sql语句,有助于提高效率。
深层次的原因还不是很懂。
<setting name="logImpl" ??? >
指定 MyBatis 所用日志的具体实现,未指定时将自动查找
settings里面内容超多,而我甚至不懂他们是干嘛的。先记住这两个吧。
子节点5:
- typeAliases 类型别名 这个好理解就是给类名全名起个简短的名字
<typeAliases> <typeAlias alias="Author" type="domain.blog.Author"/> <typeAlias alias="Blog" type="domain.blog.Blog"/> <typeAlias alias="Comment" type="domain.blog.Comment"/> <typeAlias alias="Post" type="domain.blog.Post"/> <typeAlias alias="Section" type="domain.blog.Section"/> <typeAlias alias="Tag" type="domain.blog.Tag"/> </typeAliases>
它还有另一个用法,指定一个包名,指定之后,他下面所有的Java Bean都可以仅用小写的Bean名来表示。
<typeAliases> <package name="domain.blog"/> </typeAliases>比如这个类的别名就是author,如果需要注解请用@Alias("author")
domain.blog.Author
当然,java内建类型的别名已经创建好了。如byte的别名_byte,他们不区分大小写。
节点5:无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
比如说:
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean, boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte, byte | 数据库兼容的 NUMERIC或 BYTE |
对于boolean,Boolean这两种都通过BooleanTypeHandler来进行转换
在jdbc类型和java类型中总是需要转换的。
对于非标准或者不支持类型,你可以重写TypeHandler接口,写自己的类型处理器。
休息一下.....出去锻炼了一下,顺便找了找小说的灵感,觉得搜集真人真事改编是最好得。那就继续了。
节点6:对象工厂(objectFactory)
<!-- mybatis-config.xml --> <objectFactory type="org.mybatis.example.ExampleObjectFactory"> <property name="someProperty" value="100"/> </objectFactory>
<objectFactory>标签,从配置文件这里mybatis知道调用哪个对象工厂来进行实例化。
ObjectFactory 接口很简单,它包含两个创建用的方法,一个是处理默认构造方法的,另外一个是处理带参数的构造方法的。 最后,setProperties 方法可以被用来配置 ObjectFactory,在初始化你的 ObjectFactory 实例后, objectFactory 元素体中定义的属性会被传递给 setProperties 方法。【也就是说<property标签中这个值为100的属性会传递给ObjectFactory实例。>】
要理解对象工厂,首先知道为什么要有这个工厂,mybatis创建结果对象实例得时候都是通过对象工厂来完成。
默认给出得对象工厂就是将目标类实例化,要么通过构造方法,要么在参数映射存在时通过参数得构造方法来实例化(这句不是很懂)。你可以创建你自己得工厂来覆盖默认得工厂。
// ExampleObjectFactory.java public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return super.create(type); } public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) { return super.create(type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { super.setProperties(properties); } public <T> boolean isCollection(Class<T> type) { return Collection.class.isAssignableFrom(type); }}
子节点7:拦截已映射语句的执行 【具体用法完全不懂】
首先你创建插件类,这非常简单。
实现Interceptor接口并指定想拦截的方法的签名即可
注解的方法很不错 实现这个接口就可以了 invocation调用 wrap包裹
@Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { } }
<!-- mybatis-config.xml --> <plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
配置文件里体现为plugins下一个一个插件拦截
上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, 这里的 Executor 是负责执行低层映射语
句的内部对象。
为了指定创建哪种环境,将它作为可选参数传递给SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
如果忽略了环境参数,那么默认环境将会被加载,如下所示:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
【不懂】
实际上我们操作的时候,是通过Resource的getResourceAsStream()方法读取配置文件为一个输入流,
再通过build方法加载这个输入流,来获得SqlSessionFactory的。然后openSession获取sqlSession对象。
配置文件的配置已经解释过了。
事物管理器:JDBC或者MANAGED
JDBC就是使用的jdbc的提交和回滚,通过和mysql数据库的连接来管理事务作用域。
MANAGED:这是一个傻逼,不会提交或者回滚,让容器来管理事务的整个生命周期,默认他的连接时关闭的,
你需要设置closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
<transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager>
那很关键的一点,如果你用spring+mybatis,就没必要配置事务管理器,因为spring自带的管理器会覆盖以上配置。
public interface TransactionFactory { void setProperties(Properties props); Transaction newTransaction(Connection conn); Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit); }
任何在 XML 中配置的属性在实例化之后将会被传递给 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; }
使用这两个接口,你可以完全自定义 MyBatis 对事务的处理。 一个接口负责创建事务,另一个
负责事务的代码实现。
这两种事务管理器类型都不需要任何属性(点名JDBC和MANAGED)。它们不过是类型别名,换句话说,你可以使用 TransactionFactory 接口的实现类的完全限定名或类型别名代替它们。比如说这个type的类型你完全可以用实现类的别名代替他。
关于数据源: 为了使用延迟加载,数据源必须配置,type=”[UNPOOLED|POOLED|JNDI]”
UNPOOLED:适合不需要数据池的场景。速度会慢,因为连接都是临时创建。
仅仅需要配置以下 5 种属性:
- driver – 这是 JDBC 驱动的 Java 类的完全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
- url – 这是数据库的 JDBC URL 地址。
- username – 登录数据库的用户名。
- password – 登录数据库的密码。
- defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
POOLED:创建数据池,避免了创建新的连接实例所需要的初始化和认证时间,并发web应用快速响应请求靠的就是这种方式。
他有更多的属性需要配置,好多配置。
- poolMaximumActiveConnections – 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10
- poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
- initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么 data_source 属性将会直接从 InitialContext 中寻找。
- data_source – 这是引用数据源实例位置的上下文的路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
不明白这种用来干嘛,反正是给EJB用的(企业级java bean)。
你可以通过实现接口 org.apache.ibatis.datasource.DataSourceFactory 来使用第三方数据源:
public interface DataSourceFactory { void setProperties(Properties props); DataSource getDataSource(); }
org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory 可被用作父类来构建新的数据源适配器,比如下面这段插入 C3P0 数据源所必需的代码:
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0DataSourceFactory extends UnpooledDataSourceFactory { public C3P0DataSourceFactory() { this.dataSource = new ComboPooledDataSource(); } }
为了令其工作,记得为每个希望 MyBatis 调用的 setter 方法在配置文件中增加对应的属性。下面是一个可以连接至 PostgreSQL 数据库的例子:
<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
休息一下,受不了了,开始写小说。回家再搞。最多只能专注半个小时到一个小时,这已经很极限了。
第二天。。。
仔细看,解释的蛮清楚了,databaseIdProvider用于支持数据库多厂商,
他意思就是,比如我mybatis定义了一个databaseIdProvider,那我后面匹配的语句
只要不带这个厂商id的语句,我自动舍弃。
DB_VENDOR意思为数据库厂商,具体的是根据getDatabaseProductName()返回的字符串来设置。
那返回值会和property一个一个进行匹配,如果匹到了就用匹到那个的value作为DB_VENDOR的值
否则就设置为null。比如说返回的是Oracle(DataDirect),databaseId将设置为oracle。
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/><property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
【这段没看懂在干嘛,具体我怎么设置自己的databaseId,并没有例子】
你可以通过实现接口 org.apache.ibatis.mapping.DatabaseIdProvider 并在 mybatis-config.xml 中注册来构建自己的 DatabaseIdProvider:
public interface DatabaseIdProvider { void setProperties(Properties p); String getDatabaseId(DataSource dataSource) throws SQLException; }
Mybatis的所有行为都说完了,在mybatis-config.xml中设置
接下来我们在mappers里定义SQL映射语句,
首先你需要告诉mybatis去哪里找这些映射语句
你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。
url一般就是http协议或者 File协议主要用于访问本地计算机中的文件,就如同在Windows资源管理器中打开文件一样。
<!-- 使用相对于类路径的资源引用 --> <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>
<!-- 使用映射器接口实现类的完全限定类名 --> <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 的配置文件包含了会深深影响 MyBatis 行为的设置(settings)和属性(properties)信息。文档的顶层结构如下:
- configuration 配置
- properties 属性
- settings 设置
- typeAliases 类型别名
- typeHandlers 类型处理器
- objectFactory 对象工厂
- plugins 插件
- environments 环境
- environment 环境变量
- transactionManager 事务管理器
- dataSource 数据源
- environment 环境变量
- databaseIdProvider 数据库厂商标识
- mappers 映射器
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
- cache – 给定命名空间的缓存配置。
- cache-ref – 其他命名空间缓存配置的引用。
- resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
parameterMap– 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。- sql – 可被其他语句引用的可重用语句块。
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射查询语句
对于这几个标签,我们首先关注增删改查怎么写。
多数应用也都是查询比修改要频繁。对每个插入、更新或删除操作,通常对应多个查询操作
简单查询的 select 元素是非常简单的。比如:
<select id="selectPerson" parameterType="int" resultType="hashmap"> SELECT * FROM PERSON WHERE ID = #{id} </select>
这个语句被称作 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,其中的键是列名,值便是结果行中的对应值。
简单分析一下select标签的几个属性:
1.id 用来唯一标识一个sql映射语句,与其他查询语句区别开来,其他地方调用就需要这个。
2.parameterType:将传入语句的参数类型 这个可以不写
3.参数写法:#{id}
3. select 元素有很多属性允许你配置,来决定每条语句的作用细节。
<select id="selectPerson" parameterType="int" parameterMap="deprecated" resultType="hashmap" resultMap="personResultMap" flushCache="false" useCache="true" timeout="10000" fetchSize="256" statementType="PREPARED" resultSetType="FORWARD_ONLY">
id:唯一标识符,引用这条语句需要通过id。
parameterType:参数类型,可选,不填mybatis也会自动推断。
resultType: resultType,这里填你希望返回的类型,比如说是集合,那你应该填集合类型比如hashmap,
而不是集合对象本身。
resultMap: 他和resultType很像,但你需要首先在外部写一个resultMap标签。
结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。
如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
databaseId:首先你需要配置databaseIdProvider,然后他会加载所有语句,
对于没有databaseID的语句直接忽略。 这个具体咋用还是不甚清晰。
[不懂值怎么填]resultSets:这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。
数据变更语句 insert,update 和 delete 的实现非常接近:
<insert id="insertAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" keyProperty="" keyColumn="" useGeneratedKeys="" timeout="20"> <update id="updateAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20"> <delete id="deleteAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20">
核心几个属性就是id parameterType和resultMap resultType
下面就是 insert,update 和 delete 语句的示例:
<insert id="insertAuthor"> insert into Author (id,username,password,email,bio) values (#{id},#{username},#{password},#{email},#{bio}) </insert> <update id="updateAuthor"> update Author set username = #{username}, password = #{password}, email = #{email}, bio = #{bio} where id = #{id} </update> <delete id="deleteAuthor"> delete from Author where id = #{id} </delete>
首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就OK了。例如,如果上面的 Author 表已经对 id 使用了自动生成的列类型,那么语句可以修改为:
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio}) </insert>
如果你的数据库还支持多行插入, 你也可以传入一个Authors数组或集合,并返回自动生成的主键。
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username, password, email, bio) values <foreach item="item" collection="list" separator=","> (#{item.username}, #{item.password}, #{item.email}, #{item.bio}) </foreach> </insert>
<insert>标签的子标签:
selectKey标签 意思就是插入主键
keyProperty: 主键的属性,也可以逗号隔开多个希望生成的列
keyColumn: 主键的列名
resultType: 查找到的主键类型是什么
order:填before,就是先查出主键,然后执行插入语句。after就是先插入语句,再查找主键。
我不懂有什么区别。
statementType:默认是PREPARED 预编译的语句
<insert id="insertAuthor"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1 </selectKey> insert into Author (id, username, password, email,bio, favourite_section) values (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR}) </insert>
sql:定义可重用的 SQL 代码段
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
这个 SQL 片段可以被包含在其他语句中,例如:
<select id="selectUsers" resultType="map"> select <include refid="userColumns"><property name="alias" value="t1"/></include>, <include refid="userColumns"><property name="alias" value="t2"/></include> from some_table t1 cross join some_table t2 </select>
属性值也可以被用在 include 元素的 refid 属性里(
<include refid="${include_target}"/>