由于工作关系,用到iBatis2,发现它用起来非常方便,节省了很多bean的setter,getter和参数设置、preparedStatement的操作,不用在程序中拼接大量的sql语句,而且内置支持缓存,支持动态sql,怎么个动态法呢?有点像jsp里的if标签那样,功能极为强悍,是jdbc的绝佳的替代品。3今年也出了,不过正式更名为MyBatis了,其自带的帮助文档写得很齐全了,但中文版的只有一个,看了一下,有的地方翻得很别扭,有机器翻译之嫌,所以有了自己翻译一下的冲动,结合自己的使用经验,相信会使读者一看就懂。原文60来页的篇幅,我有时间就会更新,争取每次2、3页,最少一页。P number代表原文第几页。04年的时候,第一接触iBatis,但当时英语太差,基本没看懂怎么用,觉得很复杂,所以知道英语不好的人学起来的痛苦,这也是我想翻译的初衷,因为它确实是个好东西,用过之后,你会发现,用jdbc是件多么麻烦的事情。
MyBatis下载地址: http://mybatis.org/java.html ,这里有最新版的文档和jar。
学习MyBatis最好的办法就是把自带的例子做一遍,上手很快,单看文档没有什么意义,这个文档只是一个参考手册,当你不知道某个方法怎么用的时候看一下。需要说明的是,我有些地方我采取的是意译的方法,不是直译,因为老外的思维习惯和语言习惯和中国人不太一样,直接翻会很生硬,影响理解。
P5:
MyBatis是什么?
MyBatis是支持定制sql语句、存储过程、高级映射的一级类持久化框架。MyBatis消除了几乎所有jdbc代码和对参数及结果检索的手工设置。MyBatis可以使用简洁的xml或注解来映射原始类型、Map接口和Java POJO到数据库记录。
让咱们开始吧
每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。
从xml构建SqlSessionFactory
用xml文件构建SqlSessionFactory实例是非常简单的事情。推荐在这个配置中使用类路径资源(classpath resource),但你可以使用任何Reader实例,包括用文件路径或file://开头的url创建的实例。MyBatis有一个实用类----Resources,它有很多方法,可以方便地从类路径及其它位置加载资源。如下:
String resource = "org/mybatis/example/Configuration.xml"; Reader reader = Resources.getResourceAsReader(resource); sqlMapper = new SqlSessionFactoryBuilder().build(reader);
下面这个xml配置文件包含了若干MyBatis系统的核心的设置,包括获得数据库连接实例的数据源、定义事务边界及控制事务的事务管理器。全部配置细节文件稍后在文档中可以看到,这是一个简单的例子:
<?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> <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> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
P6
当然在xml配置文件中有很多其它的细节,但上面给出的是最重要的部分。注意用来校验xml文档的xml头。environment元素的元素体包含了对事务管理器和连接池的环境配置。mappers元素包括了一个映射者的列表---包含sql源代码和映射定义的xml文件。
不用xml的情况下创建SqlSessionFactory
如果你更喜欢在Java中直接创建配置而不是xml,或者创建你自己定义的配置创建器,MyBatis有一个完善的配置类,用来提供和xml文件相同的配置。
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource(); TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); Configuration configuration = new Configuration(environment); configuration.addMapper(BlogMapper.class); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
注意此时配置中添加了一个映射者类(Mapper)。映射者是包含了sql映射注解,不使用xml的类。但由于Java注解和MyBatis映射复杂性的一些限制,xml映射仍然在一些最高级的映射中使用(如:嵌套join映射)。因此,MyBatis会自动查找相应的xml,如果它存在的话,会自动加载(在这种情况下,会根据类路径和BlogMapper.class的名字加载BlogMapper.xml)。后面有更多相应的介绍。
从SqlSessionFactory获得一个SqlSession
现在你有了SqlSessionFactory,正如名字隐含的喻义,你可以获得一个SqlSession实例。SqlSession几乎包含了所有在数据库中执行sql命令的方法。你可以直接通过SqlSession实例执行映射的sql语句。如下例:
SqlSession session = sqlMapper.openSession(); try { Blog blog = (Blog) session.selectOne( "org.mybatis.example.BlogMapper.selectBlog", 101); } finally { session.close(); }
虽然这个方法是可以的,并且和前面版本的MyBatis使用有些相似,但其实有一个更干净的办法。使用正确描述给定语句的参数和返回值的接口(如BlogMapper.class),你可以执行更干净,类型更安全的代码,而不会有字符串语义和转换的错误发生。
P7
如:
SqlSession session = sqlSessionFactory.openSession(); try { BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = mapper.selectBlog(101); } finally { session.close(); }
现在让我们来探索一下这里执行了什么吧。
探索映射sql语句
现在你可能会好奇什么东西被SqlSession和映射者类执行了。映射sql语句是一个很大的话题,它可能会占据这个文档的大部分篇幅。但为了让你知道正在运行的是什么东西,请看几个例子。
在前两个例子中,语句可以通过xml或注解来定义。让我们首先看一下xml。完整的功能点可以通过基于xml的映射语言来体会到,这也是MyBatis风靡多年的一个原因。如果你以前用过MyBatis,此概念对你来说很熟悉,现在有了很多xml映射文档的改进,后面会有更明晰的介绍。下面是一个基于xml的映射语句,用于供SqlSession调用。
<?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="org.mybatis.example.BlogMapper"> <select id="selectBlog" parameterType="int" resultType="Blog"> select * from Blog where id = #{id} </select> </mapper>
对于一个简单的例子,这看起来有点晕,其实不是。你可以按自己的意愿,在一个映射者xml文件中定义很多映射语句,这是定义了xml头和doctype声明的好处。文件的其它部分一目了然,见名知意。它定义了映射语句的名字叫“selectBlog”,位于org.mybatis.example.BlogMapper的命名空间,它要求你使用映射语句的时候,要定义全限定的名字---org.mybatis.example.BlogMapper.selectBlog,正如下例中我们为了前例所做的事情:
Blog blog = (Blog) session.selectOne(
"org.mybatis.example.BlogMapper.selectBlog", 101);
注意看,这和调用一个全限定Java类很相似,并且这么做是有理由的,这个名字可以通过和映射select语句匹配的名字、参数及返回类型,直接映射到一个和命名空间同名的映射者类。这让你可以非常简单地通过映射者接口调用,下面再次提一个这个例子:
Blog blog = (Blog) session.selectOne(
"org.mybatis.example.BlogMapper.selectBlog", 101);
第二个方法有很多好处。首先,它不依赖于字符串语义,所以更安全,其次,如果你的IDE支持代码完成,当IDE导航并发现这些sql语句的时候,它可以被用到。第三,你不必转换返回类型,因为BlogMapper有干净、类型安全的返回类型(还有一个类型安全的参数)