至从“关系数据库之父”Edgar F Codd提出《A Relational Model of Data for Large Shared Data Banks》(大型共享数据库数据的关系模型)标志着关系型数据库理论基础的诞生;再到1978年Oracle公司(原来叫)发布世界上第一个关系型数据库,标志着数据库已经可以运用到实际用途中。三十多年来,关系型数据库在各行各业的应用,都得到了蓬勃发展。即使最近今年,NoSQL技术发胀的如火如荼。但是,在银行、证券等行业,关系型数据库在数据存储中的地位短时间内依然是无可替代!
1975年推出的Smalltalk语言,是第一个完整实现的面向对象语言,向人们展示了“面向对象编程思想”的强大!并且,随着1995年Java技术的推出,以及以后Java在各个领域的大规模成功应用,另外微软推出的C#,PHP对面向对象支持力度的提高,更是把“面向对象编程思想”推向了高潮!
程序离开了数据,就一无是处、百无一用!数据离开了程序,就等于宣布了数据的死期!但是,关系型数据库是“面向集合”的;Java编程是“面向对象”的。这就存在一个“映射不对称性”。为了解决这个问题,我们的前辈提出来“O/R Mapping”技术,而MyBATIS、Hibernate是这里的两个比较优秀的开源解决方案!今天,我们就用实例来讲解一下MyBATIS。
有点背景需要说明一下,由于计划分享一个SpringMVC+Spring+MyBATIS整合的说明文章。所以,将这个入门当成“整合”文章的第一部分。另外,这里的业务场景是:基于数据库,完成对用户的增删改查。
先在MyEclipse中建一个”Web Project”,名字就叫”SSM”(这个可以随意取,我是为了搭建一个空工程,方便以后使用)。然后,在工程中,新建两个"Source Folder",分别命名为cfg(Configuration,存放配置文件)、test(存放测试用例);在WEB-INF/lib下,新建两个目录,MySQL和MyBATIS,然后把MySQL,和MyBATIS的Jar包分别拷贝到这个目录中。选中两个Jar把,”Add Build Path”一下。如下图:

图1-添加MySQL和MyBATIS的Jar包
另外,测试的时候需要使用JUnit。所以,将MyEclipse自带的JUnit v4的类库添加到“Build Path”中。
由于MyBATIS是一个O/R Mapping框架。我们首先需要建立起来Java中的对象和数据库中的表。具体代码如下:
用户User模型代码如下:
01 | package com.diguage.ssm.domain; |
12 | private Date birthday; |
14 | private String password; |
请注意这个类中package名。为了方便统一管理,将所有的包都放在com.diguage.ssm下,在这个包的下面另外建立domain(存放领域模型)、dao(存放数据访问)。
user表建表语句如下(另外,请在MySQL中,新建ssm数据库,然后在这里数据库中新建下表):
01 | DROP TABLE IF EXISTS ` user `; |
03 | `id` int (11) NOT NULL AUTO_INCREMENT, |
10 | ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE =utf8_bin; |
有了这两个基础,我们就可以写User类的映射文件了。映射文件的书写可以参考《MyBATIS User Guide》(“参考资料”中给出了中/英文版的下载链接),这里就直接给出配置文件(注意,这个文件放在和User类同一个包里。)里:
01 | <? xml version = "1.0" encoding = "UTF-8" ?> |
03 | PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
05 | < mapper namespace = "com.diguage.ssm.domain.UserMapper" > |
07 | < select id = "query" parameterType = "int" resultType = "User" > |
12 | < insert id = "save" parameterType = "User" useGeneratedKeys = "true" |
13 | keyProperty = "id" flushCache = "true" > |
14 | INSERT INTO user (name, password, sex, birthday, email) |
16 | (#{name}, #{password}, #{sex}, #{birthday}, #{email}) |
19 | < update id = "update" parameterType = "User" > |
22 | password = #{password}, |
24 | birthday = #{birthday}, |
30 | < delete id = "delete" parameterType = "int" > |
31 | DELETE FROM user WHERE |
在我看来,这个映射文件就是建立在数据库表和Java对象之间的一个虚“拟机”,屏蔽两者之间的差异,时使其可以协同工作。这里需要注意的是namespace属性。在一个稍微大型一点的系统,命名冲突是一个很头疼的问题。Java通过package来区分,这里使用这个namespace属性来区分。
到这里,我们就能开始“配置”MyBATIS了。MyBATIS的映射文件和Hibernate的映射文件类似;而MyBATIS的配置文件和Hibernate的hibernate.cfg.xml文件类似。从这点上来说,我感觉这这两框架有一腿。呵呵
01 | <? xml version = "1.0" encoding = "UTF-8" ?> |
02 | <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" |
06 | < properties resource = "jdbc.properties" /> |
09 | < typeAlias alias = "User" type = "com.diguage.ssm.domain.User" /> |
12 | < environments default = "development" > |
13 | < environment id = "development" > |
14 | < transactionManager type = "JDBC" /> |
15 | < dataSource type = "POOLED" > |
16 | < property name = "driver" value = "${driver}" /> |
17 | < property name = "url" value = "${url}" /> |
18 | < property name = "username" value = "${username}" /> |
19 | < property name = "password" value = "${password}" /> |
25 | < mapper resource = "com/diguage/ssm/domain/UserMapper.xml" /> |
注意这个配置文件(存放到上面新建的cfg文件夹下)中的typeAlias标签。从上面的User类的代码中,可以看出User类的权限定名是:com.diguage.ssm.domain.User。但是,我们在映射文件UserMapper.xml中写的都是User。正是因为我在这里使用这个typeAlias,给User类起了个别名,才可以在映射文件中简写成User。另外,注意这里的mapper标签,使用resource属性说明一下映射文件的位置。
也许细心的配置已经注意到了,这里别没有写JDBC链接数据库的一些必要信息。但是有“properties”这个标签。我个人认为,把数据库链接信息提取出来单独放到一个文件中比较好。所以,这里还有一个property文件(存放在上面新建的cfg文件夹下,同时根据自己的实际情况修改MySQL的链接信息),用于存放数据库链接信息。内容如下:
1 | driver=com.mysql.jdbc.Driver |
这里说明一下,URL中需要带上useUnicode=true&characterEncoding=UTF-8,否则可能会出现乱码我问题
到这里,我们还没写过几段代码,下面我们就正在开始,在上面新建的test文件下,新建MyBATISTest.java,代码如下:
01 | package com.diguage.ssm.dao; |
03 | import java.io.IOException; |
04 | import java.io.InputStream; |
07 | import org.apache.ibatis.io.Resources; |
08 | import org.apache.ibatis.session.SqlSession; |
09 | import org.apache.ibatis.session.SqlSessionFactory; |
10 | import org.apache.ibatis.session.SqlSessionFactoryBuilder; |
11 | import org.junit.After; |
12 | import org.junit.Before; |
13 | import org.junit.BeforeClass; |
16 | import com.diguage.ssm.domain.User; |
18 | public class MyBATISTest { |
19 | private static SqlSessionFactory sessionFactory = null ; |
20 | private SqlSession session = null ; |
23 | public static void init() throws IOException { |
25 | String resource = "MyBATISConfig.xml" ; |
26 | InputStream inputStream = Resources.getResourceAsStream(resource); |
27 | sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); |
31 | public void operSession() { |
33 | session = sessionFactory.openSession( true ); |
37 | public void closeSession() { |
43 | User user = new User(); |
44 | user.setBirthday( new Date()); |
46 | user.setEmail( "123@abc.com" ); |
47 | user.setPassword( "MyPass" ); |
49 | session.insert( "com.diguage.ssm.domain.UserMapper.save" , user); |
50 | System.out.println( "新生成的主键是:" + user.getId()); |
54 | public void delete() { |
55 | session.delete( "com.diguage.ssm.domain.UserMapper.delete" , 4 ); |
59 | public void update() { |
60 | User u = session.selectOne( "com.diguage.ssm.domain.UserMapper.query" , 3 ); |
61 | System.out.println(u.getPassword()); |
62 | u.setPassword( "diguage.com" ); |
63 | session.update( "com.diguage.ssm.domain.UserMapper.update" , u); |
68 | User u = session.selectOne( "com.diguage.ssm.domain.UserMapper.query" , 3 ); |
69 | System.out.println(u.getName()); |
70 | System.out.println(u.getEmail()); |
这里,我想说明一点,在运行save方法时,可以看出,已经新生成了“主键”id。所以,这里也就回答了“MyBATIS(即iBATIS)问题集”中的第九个问题。
这个文章写的有点“仓促”。很多地方没有说明白,以后再慢慢说明。另外,也可以看“MyBATIS User Guide”。里面说明了很多问题。(只是例子写的有点零散。不过,有我的这个例子,可以相互参考着学习。希望对各位感兴趣的朋友有帮助。
想用微博分享,但是不知道为啥不行。需要的话,给我私信吧。抱歉!
参考资料: