Mybatis架构学习

MyBatis 是支持定制化 SQL、存储过程以及高级映射的持久层框架。MyBatis 封装了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录.

项目中使用mabatis只需要引入mybatis-3.4.1.zip包,或添加maven dependency如下

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>

1.克隆Mybatis代码

mabatis  https://github.com/mybatis/mybatis-3.git

mabatis/parent   https://github.com/mybatis/parent.git

2.使用maven构建 mabatis/parent 项目

  1.进入mabatis/parent目录

  2.$mvn install

3.用Maven将mabatis代码导入IntelliJ IDEA(首先安装maven插件)

4.构建mybatis

6.调试

7.框架

SqlSessions

SqlSession是Mybatis中重要的接口。可以使用它执行命令,获取映射器和管理事务。SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的所有方法 。而 SqlSessionFactory本身是 由 SqlSessionFactoryBuilder 创建的,它可以从 XML 配置,注解或手动配置 Java 来创建 SqlSessionFactory。

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 有五个 build()方法,每一种都允许你从不同的资源中创建一个 SqlSession 实例。

SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)
SqlSessionFactory build(Configuration config)

第一种方法使用了 mybatis-config.xml 文件的 Reader 实例。 可选的参数是 environment 和 properties。 Environment 决定加载哪种环境,包括数据源和事务管理器。比如:

<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
...
<dataSource type="POOLED">
...
</environment>
<environment id="production">
<transactionManager type="MANAGED">
...
<dataSource type="JNDI">
...
</environment>
</environments>

如果调用了一个使用 environment 参数方式的build方法, 那么MyBatis将会使用configuration对象来配置这个environment。 当然, 如果指定了一个不合法的 environment, 你会得到错误提示。 如果你调用了其中之一没有 environment 参数的 build 方法, 那么就使用 默认的 environment(在上面的示例中就会指定为 default=”development”)。

如果你调用了使用 properties 实例的方法,那么 MyBatis 就会加载那些 properties(属性 配置文件) ,并你在你配置中可使用它们。那些属性可以用${propName}语法形式多次用在 配置文件中。

回想一下,属性可以从 mybatis-config.xml 中被引用,或者直接指定它。因此理解优先 级是很重要的。我们在文档前面已经提及它了,但是这里要再次重申:


如果一个属性存在于这些位置,那么 MyBatis 将会按找下面的顺序来加载它们:

  • 在 properties 元素体中指定的属性首先被读取,
  • 从 properties 元素的类路径 resource 或 url 指定的属性第二个被读取, 可以覆盖已经 指定的重复属性,
  • 作为方法参 数传递 的属性最 后被读 取,可以 覆盖已 经从 properties 元 素体和 resource/url 属性中加载的任意重复属性。

因此,最高优先级的属性是通过方法参数传递的,之后是 resource/url 属性指定的,最 后是在 properties 元素体中指定的属性。


总结一下,前四个方法很大程度上是相同的,但是由于可以覆盖,就允许你可选地指定 environment 或 properties。 这里给出一个从 mybatis-config.xml 文件创建 SqlSessionFactory 的示例:

String resource = "org/mybatis/builder/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);

Resources工具类在org.mybatis.io包中,它可以从类路径下,文件系统或一个web URL加载资源文件,有如下方法:

URL getResourceURL(String resource)
URL getResourceURL(ClassLoader loader, String resource)
InputStream getResourceAsStream(String resource)
InputStream getResourceAsStream(ClassLoader loader, String resource)
Properties getResourceAsProperties(String resource)
Properties getResourceAsProperties(ClassLoader loader, String resource)
Reader getResourceAsReader(String resource)
Reader getResourceAsReader(ClassLoader loader, String resource)
File getResourceAsFile(String resource)
File getResourceAsFile(ClassLoader loader, String resource)
InputStream getUrlAsStream(String urlString)
Reader getUrlAsReader(String urlString)
Properties getUrlAsProperties(String urlString)
Class classForName(String className)

最后一个 build 方法使用了一个 Configuration 实例。configuration 类包含你可能需要了 解 SqlSessionFactory 实例的所有内容。Configuration 类对于配置的自查很有用,包含查找和 操作 SQL 映射(不推荐使用,因为应用正接收请求) 。configuration 类有所有配置的开关, 这些你已经了解了,只在 Java API 中露出来。这里有一个简单的示例,如何手动配置 configuration 实例,然后将它传递给 build()方法来创建 SqlSessionFactory。

DataSource dataSource = BaseDataTest.createBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); Configuration configuration = new Configuration(environment);
configuration.setLazyLoadingEnabled(true);
configuration.setEnhancementEnabled(true);
configuration.getTypeAliasRegistry().registerAlias(Blog.class);
configuration.getTypeAliasRegistry().registerAlias(Post.class);
configuration.getTypeAliasRegistry().registerAlias(Author.class);
configuration.addMapper(BoundBlogMapper.class);
configuration.addMapper(BoundAuthorMapper.class); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(configuration);

SqlSessionFactory

SqlSessionFactory 有六个方法可以用来创建 SqlSession 实例。通常来说,如何决定是你 选择下面这些方法时:

  • Transaction (事务): 你想为 session 使用事务或者使用自动提交(通常意味着很多 数据库和/或 JDBC 驱动没有事务)?
  • Connection (连接): 你想 MyBatis 获得来自配置的数据源的连接还是提供你自己
  • Execution (执行): 你想 MyBatis 复用预处理语句和/或批量更新语句(包括插入和 删除)?

重载的 openSession()方法签名设置允许你选择这些可选中的任何一个组合。

SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();

默认的 openSession()方法没有参数,它会创建有如下特性的 SqlSession:

  • 会开启一个事务(也就是不自动提交)
  • 连接对象会从由活动环境配置的数据源实例中得到。
  • 事务隔离级别将会使用驱动或数据源的默认设置。
  • 预处理语句不会被复用,也不会批量处理更新。

autoCommit参数设置开启自动提交,  connection提供自定义的连接。

MyBatis 为事务隔离级别调用使用一个 Java 枚举包装器, 称为 TransactionIsolationLevel, 否则它们按预期的方式来工作,并有 JDBC 支持的 5 级 ( NONE,READ_UNCOMMITTED,READ_COMMITTED,REPEA TABLE_READ,SERIALIZA BLE)

ExecutorType定义了3个值:

  • ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。
  • ExecutorType.REUSE: 这个执行器类型会复用预处理语句。
  • ExecutorType.BATCH: 这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行还会标定它们是 必须的,来保证一个简单并易于理解的行为。

SqlSessionFactory有一个方法getConfiguration()返回一个Configuration实例,在运行时可以用它来获取MyBatis的配置。

之前版本MyBatis, session,transaction和batch都是分离的,现在这些都包含在session的范围内。

SqlSession

SqlSession的方法很多,有执行语句的方法,提交或回滚事务和获取映射器实例的方法:

语句执行方法

执行定义在Mapper中的 SELECT,INSERT,UPDAET 和 DELETE。它们都会自行解释,每一句都使用ID属性和参数对象,参数可以是原生类型(自动装箱或包装类) ,JavaBean,POJO 或 Map。

<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)

selectOne和selectList的不同是 selectOne 必须返回一个对象。 如果多余一个, 或者没有返回 或返回了null 就会抛出异常 , 如果你不知道返回多少对象, 就使用selectList。

还有另外3个查询方法,它们允许限制返回行数的范围,或者提供自定义结果控制逻辑,这通常用于大量的数据集合。

<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler<T> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)

RowBounds 参数会告诉 MyBatis 略过指定数量的记录,还有限制返回结果的数量。 RowBounds 类有一个构造方法来接收 offset 和 limit,否则是不可改变的。

int offset = 100, limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);

不同的驱动会实现这方面的不同级别的效率。对于最佳的表现,使用结果集类型的 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE(或句话说:不是 FORWARD_ONLY)。

ResultHandler 参数允许你按你喜欢的方式处理每一行。你可以将它添加到 List 中,创 建 Map, 或抛出每个结果而不是只保留总计。 Set 你可以使用 ResultHandler 做很多漂亮的事, 那就是 MyBatis 内部创建结果集列表。

它的接口很简单。

package org.apache.ibatis.session;
public interface ResultHandler<T> {
void handleResult(ResultContext<? extends T> context);
}

ResultContext 参数给你访问结果对象本身的方法, 大量结果对象被创建, 你可以使用布 尔返回值的 stop()方法来停止 MyBatis 加载更多的结果。

Batch update statement Flush Method

There is method for flushing(executing) batch update statements that stored in a JDBC driver class at any timing. This method can be used when you use the ExecutorType.BATCH as ExecutorType.

List<BatchResult> flushStatements()
事务控制方法

控制事务范围有四个方法。 当然, 如果你已经选择了自动提交或你正在使用外部事务管 理器,这就没有任何效果了。然而,如果你正在使用 JDBC 事务管理员,由 Connection 实 例来控制,那么这四个方法就会派上用场:

void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)

默认情况下 MyBatis 不会自动提交事务, 除非它侦测到有插入, 更新或删除操作改变了数据库。如果已经做出了一些改变而没有提交,那么可以传递 true 到 commit 和 rollback 方法来保证它会被提交.

清理 Session 级的缓存
void clearCache()

SqlSession 实例有一个本地缓存在执行 update,commit,rollback 和 close 时被清理。要 明确地关闭它(获取打算做更多的工作) ,你可以调用 clearCache()。

关闭SqlSession
void close()

你必须保证的最重要的事情是你要关闭所打开的任何 session。保证做到这点的最佳方 式是下面的工作模式:

SqlSession session = sqlSessionFactory.openSession();
try {
// following 3 lines pseudocod for "doing some work"
session.insert(...);
session.update(...);
session.delete(...);
session.commit();
} finally {
session.close();
}

getConfiguration()方法可获得SqlSession使用的Configuration实例

使用映射器
<T> T getMapper(Class<T> type)

上述的各个 insert,update,delete 和 select 方法都很强大,但也有些繁琐,没有类型安 全,对于你的 IDE 也没有帮助,还有可能的单元测试。在上面的入门章节中我们已经看到 了一个使用映射器的示例。

因此, 一个更通用的方式来执行映射语句是使用映射器类。 一个映射器类就是一个简单 的接口,其中的方法定义匹配于 SqlSession 方法。下面的示例展示了一些方法签名和它们是 如何映射到 SqlSession 的。

public interface AuthorMapper {
// (Author) selectOne("selectAuthor",5);
Author selectAuthor(int id);
// (List<Author>) selectList(“selectAuthors”)
List<Author> selectAuthors();
// (Map<Integer,Author>) selectMap("selectAuthors", "id")
@MapKey("id")
Map<Integer, Author> selectAuthors();
// insert("insertAuthor", author)
int insertAuthor(Author author);
// updateAuthor("updateAuthor", author)
int updateAuthor(Author author);
// delete("deleteAuthor",5)
int deleteAuthor(int id);
}

总之, 每个映射器方法签名应该匹配相关联的 SqlSession 方法, 而没有字符串参数 ID。 相反,方法名必须匹配映射语句的 ID。

此外,返回类型必须匹配期望的结果类型。所有常用的类型都是支持的,包括:原生类 型,Map,POJO 和 JavaBean。

映射器接口不需要去实现任何接口或扩展任何类。 只要方法前面可以被用来唯一标识对 应的映射语句就可以了。

映射器接口可以扩展其他接口。当使用 XML 来构建映射器接口时要保证在合适的命名 空间中有语句。 而且, 唯一的限制就是你不能在两个继承关系的接口中有相同的方法签名 (这 也是不好的想法)。

你可以传递多个参数给一个映射器方法。 如果你这样做了, 默认情况下它们将会以它们 在参数列表中的位置来命名,比如:#{param1},#{param2}等。如果你想改变参数的名称(只在多参数 情况下) ,那么你可以在参数上使用@Param(“paramName”)注解。

你也可以给方法传递一个 RowBounds 实例来限制查询结果。

映射器注解

因为最初设计时,MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,而且 映射语句也是定义在 XML 中的。而到了 MyBatis 3,有新的可用的选择了。MyBatis 3 构建 在基于全面而且强大的 Java 配置 API 之上。这个配置 API 是基于 XML 的 MyBatis 配置的 基础,也是新的基于注解配置的基础。注解提供了一种简单的方式来实现简单映射语句,而 不会引入大量的开销。

注意 不幸的是,Java 注解限制了它们的表现和灵活。尽管很多时间都花调查,设计和 实验上,最强大的 MyBatis 映射不能用注解来构建,那并不可笑。C#属性(做示例)就没 有这些限制,因此 MyBatis.NET 将会比 XML 有更丰富的选择。也就是说,基于 Java 注解 的配置离不开它的特性。

日志:

Mybatis支持多种日志工具, slf4j, commonloging, log4j和 jdklogging.  LogFactory为其反射静态工厂.

例如log4j,在log4j.properties中配置如下

# Global logging configuration
log4j.rootLogger=ERROR, stdout # MyBatis logging configuration
# 指定mapper的namespace
log4j.logger.mapperpath/namespace=TRACE
# 只打印select语句
log4j.logger.mapperpath/namespace.selectOper=TRACE
# 指定dao层接口
log4j.logger.packagepath.interfacename=TRACE # Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

------------

Mybatis代码学习的更多相关文章

  1. Mybatis架构学习

    Mybatis架构学习 MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架.MyBatis 封装了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.可以对配置和原生Map使用 ...

  2. MyBatis入门学习教程-使用MyBatis对表执行CRUD操作

    上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...

  3. MyBatis入门学习(二)

    在MyBatis入门学习(一)中我们完成了对MyBatis简要的介绍以及简单的入门小项目测试,主要完成对一个用户信息的查询.这一节我们主要来简要的介绍MyBatis框架的增删改查操作,加深对该框架的了 ...

  4. Mybatis的学习总结二:使用Mybatis对表进行CRUD操作【参考】

    一.使用Mybatis对表进行CRUD操作------基于XML的实现 1.定义SQL的映射文件 2.在conf.xml中进行注册. 2.创建测试类 [具体过程参考:Mybatis的学习总结一] 二. ...

  5. Spring+SpringMVC+MyBatis深入学习及搭建(二)——MyBatis原始Dao开发和mapper代理开发

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6869133.html 前面有写到Spring+SpringMVC+MyBatis深入学习及搭建(一)——My ...

  6. Spring+SpringMVC+MyBatis深入学习及搭建(四)——MyBatis输入映射与输出映射

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6878529.html 前面有讲到Spring+SpringMVC+MyBatis深入学习及搭建(三)——My ...

  7. Spring+SpringMVC+MyBatis深入学习及搭建(五)——动态sql

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6908763.html 前面有讲到Spring+SpringMVC+MyBatis深入学习及搭建(四)——My ...

  8. Spring+SpringMVC+MyBatis深入学习及搭建(七)——MyBatis延迟加载

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6953005.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(六)——My ...

  9. Spring+SpringMVC+MyBatis深入学习及搭建(十)——MyBatis逆向工程

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6973266.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(九)--My ...

随机推荐

  1. problem-1003(恢复一下)

    问题: Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequenc ...

  2. linux输入子系统简述【转】

    本文转载自:http://blog.csdn.net/xubin341719/article/details/7678035 1,linux输入子系统简述 其实驱动这部分大多还是转载别人的,linux ...

  3. 微信内置浏览器和小程序的 User Agent 区别及判断方法

    通过UA来判断不同的设备或者浏览器是开发者最常用的方式方法,而对于微信开发和小程序也是同样的一个情况,我们可以通过微信内置浏览器 User Agent 信息来判断其具体类型或者设备. 所以子凡就通过徒 ...

  4. Eclipse Validating缓慢的优化

    使用Eclipse的人基本都有这种情况,如图: 各种等待有木有,各种崩溃啊有木有,反正我是觉得挺烦的,但是也不知道是干嘛的,如果取消了,造成程序出问题,就是给自己找麻烦,我知道这个事情肯定是可以关的, ...

  5. 解决spring、springMVC重复扫描导致事务失效的问题

    在主容器中(applicationContext.xml),将Controller的注解排除掉 1 2 3 而在springMVC配置文件中将Service注解给去掉 1 2 3 4 因为spring ...

  6. Linux FTP 上传一键脚本

    下面来介绍一下这个 FTP 上传一键脚本 ftp_upload.sh. 用途:用于在Linux系统下搭建FTP客户端向FTP服务器端上传文件: 总结一下 ftp_upload.sh 特点:1.支持文件 ...

  7. 为什么可以Ping通IP地址,但Ping不通域名?

    能否ping通IP地址,与能否解析域名是两回事不能ping通IP地址,说明对方禁止ICMP报文或对方没有开机等解析域名只是将域名翻译成IP地址,不论该IP地址是否能够正常访问 问题是ping域名的时候 ...

  8. 使用Homebrew管理你的mac开发包

    很多人可能不了解 Homebrew, 其实它相当于开发软件界的 Appstore. 比如,如果我要安装 python 的最新版本,那么传统的做法是 1. 到官方网站下载 python 的最新版本 2. ...

  9. 关于UML方法学图中类之间的关系:依赖,泛化,关联

    类与类图 1) 类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性.操作.关系的对象集合的总称. 2) 在系统中,每个类具有一定的职责,职责指的是类所担任的任务,即类要完成什 ...

  10. list!=null跟list.isEmpty()有什么区别?

    这就相当与,你要喝水,前面list!=null就是判断是不是连水杯都没有,后面!list.isEmpty就是判断水杯里面没有水,连盛水的东西都没有,这个水从何而来?所以一般的判断是if(list!=n ...