Mybatis(二)标签深入总结

前天已经把mybatis的搭建步骤都写的很详细了,那会搭之后,就是要能让他为我们所用,它里面提供了丰富的功能。

那mybatis其实也没有什么神奇的,首先你需要会搭建。
其次就是知道怎么写配置文件,因为mybatis是通过核心配置文件来控制的。

写配置文件的步骤:1.首先创建mybatis-config.xml,在哪里创建。

我们老师喜欢在src/main/java里建,我可能就是创建一个source folder叫resource,其实效果都一样,都是在一个源码文件夹里创建,为啥都是放source folder里,因为java文件放里面是可以编译的。源码文件夹里还可以创建多个包。他俩的区别,source folder下面可以创建package,反之则不行,另外source folder用/连接上下级,package用.  来连接上下级。如果source套着package,具体我没写过,不知道路径怎么写才对。但是看老师写的应该是只要在source folder里都要用/来连接。

包名/类名。


2.mybatis-config里的标签

头文件:对mybatis进行约束,如必须有哪些节点。
根节点:<configuration></configuration> 


子节点1 : <environments default="development">

规定mybatis的运行环境,下面可以有多个<environment id="development">标签可以对事物、数据源进行管理,通过id来标识每套环境:

(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>
  <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 类型
BooleanTypeHandlerjava.lang.Booleanboolean数据库兼容的 BOOLEAN
ByteTypeHandlerjava.lang.Bytebyte数据库兼容的 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)信息。文档的顶层结构如下:


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}"/>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值