(一)前身iBatis
网上发现MyBatis书很少,因为旧项目用到的是ibatis,所以先大致过了iBatis,因为太老,所以基本上讲解的东西好少,但是还有《iBatis实战》这本书,再结合一下像iBatis tutorial这样的东西,敲敲代码,基本上就能把简单的增删改查给写出来,以前编程刚入门的时候,感觉看视频比较好,后面就改了自己的学习方法了,视频太久,看书更快,不过每个人的学习方法不同。但是这个没写出来,只是做了一下笔记,毕竟,现在已经都用MyBatis了。
MyBatis是iBatis项目迁移后的改名,iBatis3.x的项目正式改名为MyBatis,iBatis教程里面的是iBatis2.x版本。
MyBatis的jar包中仍然是org.apache.ibatis。
学过Hibernate的知道,Hibernate基本上不用写什么SQL,是完全的ORM,对象关系映射。
而传统的JDBC是直接拼出SQL去执行操作。
iBatis介于这两者之间,要写SQL,但是又不像传统JDBC那样死,所以书上说的是正确的,iBatis不算是真正的ORM,算个半自动的ORM。书里描述它是查询映射工具。
当然优点是显而易见的,但是缺点也是有的:
1、如果是多表的关联查询再加上条件,那么xml配置里面配置起来十分复杂。
2、参数传入不灵活,多参数的话一般传入对象中。
3、sql语句是在标签里面的,配置不方便。
而MyBatis迁到Github之后,资料全了好多,但是文档还是有点鸡肋,有些东西没能解释清楚。
不过,这就是一手资料。
http://mybatis.github.io/mybatis-3/zh/index.html
读完这些会发现和iBatis好像,不同的是有着SqlSessionFactory这样的工厂控制SqlSession,一想就想到Hibernate的SessionFactory了。
把文档基本过了并写例子程序,也发现了中文翻译里面的一些错误,作为一名开发者,肯定要改正这些错误。
所以,我在github修改后并pull requests。然后得到一个日本、一个加拿大、一个西班牙的开发者的合并。
然后,我也成为了一名contributor。以前从没为开源项目做过什么贡献,虽然只是改了一些小错误,但是能得到开源项目来自世界各地的开发者的认可,那种自豪和成就感很大。
(二)基础环境的搭建
找到mybatis的github地址:https://github.com/mybatis/mybatis-3
一般README.md文档就有详细介绍,哪里下载jar包,一般找download的字眼就很容易找到了。
然后进入页面最底部的 Download Lastest。
下载需要的包:
自己新建工程,build path引进相关资源包。项目使用的是Mysql。
然后根据一手资料。
用maven的话自己添加就好了。我这里的是整合SpringMVC的,仅供参考。
<dependency><groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-library -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.4 </version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.4 </version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>net.rossillo.mvc.cache</groupId>
<artifactId>spring-mvc-cache-control</artifactId>
<version>1.1.1-RELEASE</version>
<scope>compile</scope>
</dependency>
http://mybatis.github.io/mybatis-3/zh/index.html
大概能写个简单的例子。
先建数据表:
USE `test`;CREATE TABLE `employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `first_name` varchar(20) DEFAULT NULL, `last_name` varchar(20) DEFAULT NULL, `salary` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;/*Data for the table `employee` */insert into `employee`(id,first_name,last_name,salary) values (7,'bbb','ccc',10000),(8,'a','b',100),(9,'a','b',100),(10,'a','b',100),(11,'a','b',100),(12,'a','b',100),(13,'a','b',100);
建好后的模型:
整个工程的代码目录:
Employee.java,根据数据库建模:
package com.mybatis.test;import org.apache.ibatis.type.Alias;public class Employee { private int id; private String first_name; private String last_name; private int salary; /* Define constructors for the Employee class. */ public Employee() {} public int getId() {return id;}public void setId(int id) {this.id = id;}public String getFirst_name() {return first_name;}public void setFirst_name(String first_name) {this.first_name = first_name;}public String getLast_name() {return last_name;}public void setLast_name(String last_name) {this.last_name = last_name;}public int getSalary() {return salary;}public void setSalary(int salary) {this.salary = salary;}public Employee(String fname, String lname, int salary) { this.first_name = fname; this.last_name = lname; this.salary = salary; }}
mybatis-config.xml
<?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="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="EmployeeMapper.xml"/> </mappers></configuration>
EmployeeMapper.xml
<?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="EmployeeMapper"> <select id="selectEmployee" resultType="com.mybatis.test.Employee"> select * from Employee where id = #{id} </select></mapper>
Factory.java
package com.mybatis.test;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Iterator;import org.apache.ibatis.annotations.Select;import org.apache.ibatis.io.Resources;import org.apache.ibatis.jdbc.SQL;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class Factory {public static void main(String[] args) {String configxml = "mybatis-config.xml";InputStream is = null;try {is = Resources.getResourceAsStream(configxml);} catch (IOException e) {e.printStackTrace();}SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);SqlSession s = sf.openSession();//select * from employee by idEmployee e = s.selectOne("EmployeeMapper.selectEmployee",8);System.out.println(e.getFirst_name());System.out.println(e.getLast_name());System.out.println(e.getSalary());s.close();}}
通过读取mybatis-config.xml,mybatis文件有相应的EmployeeMapper.xml,EmployeeMapper映射了相应的JavaBean,通过SqlSessionFactory的实例化出来的SqlSession,执行对应方法,根据方法名EmployeeMapper.selectEmployee,回到EmployeeMapper.xml中找到和方法名相对应的id,根据sql语句,还有传入的参数,还有Bean,这几者的联系形成的映射,进行CURD操作,最后的结果:
为什么这次代码里面不加注释了:请看文章后面的部分。
log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).log4j:WARN Please initialize the log4j system properly.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.ab100
log4j有点问题,如果没有添加对应jar包的话。添加maven依赖和添加log4j.properties即可。
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version></dependency><!-- https://mvnrepository.com/artifact/log4j/log4j --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency>
查看中文文档可以发现有个关于日志的:添加log4j.properties:
# Global logging configurationlog4j.rootLogger=ERROR, stdout# MyBatis logging configuration...log4j.logger.org.mybatis.example.BlogMapper=TRACE# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m %nlog4j.logger.com.mybatis.test=DEBUGlog4j.logger.EmployeeMapper=DEBUG
接下来的输出:
DEBUG [main] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@7185c517]DEBUG [main] - ==> Preparing: select * from Employee where id = ? DEBUG [main] - ==> Parameters: 8(Integer)ab100
使用java进行映射:
上面的是根据xml进行映射的。
可以直接用接口进行映射。
package com.mybatis3.mappers;public interface EmployeeMapper{Employee findEmployeeById(Integer id);}
<?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="com.mybatis3.mappers.EmployeeMapper"> <select id="findEmployeeById" resultType="model.Employee"> select * from Employee where id = #{id} </select> </mapper>
mybati-config.xml中原本的xml映射改为类的映射:
<mappers><mapper class="com.mybatis3.mappers.EmployeeMapper" /></mappers>
Factory中的操作改为:
EmployeeMapper employeeMapper = s.getMapper(EmployeeMapper.class); Employee e = employeeMapper.findEmployeeById(8); System.out.println(e.getFirst_name()); System.out.println(e.getLast_name()); System.out.println(e.getSalary());
(三)如何钓鱼。
近期一边在学习MyBatis,一边在看《我编程,我快乐》这本书,为什么我会来写这篇呢?书对刚开始职业生涯的人来说还是挺有用的。要懂得如何钓鱼,刚开始的时候,被人把做好的鱼送给你,确实方便又来的快,但是哪天这个人不在了,你自己一个人要怎么钓鱼呢?就好比看书,看视频,是别人了解了第一手资料的情况下,别人整理出来的东西,所以搞研究的就不停地看论文。
如果哪天是你自己先看到这个框架的,你能自己通过官方的然后写出你平时在看别人的那种样子的教程吗?或者不看别人的二手资料你自己能自己搭建好框架然后运行自己的代码吗?
如果可以了,那你自己也学会钓鱼了。
前面提到的为什么我不给代码加注释了,因为,我想的是你直接进官网的文档直接动手敲,再结合我的例子看足矣。
因为这篇文章不想写成MyBatis实战一、二、三、四这样的文章了,毕竟已经有这样的文章的存在,还有书。
工作之后,我发现时间并不像学生时代那样充裕,所以并没有太多的时间再把我学习的一个一个例子再放到上面来了,但是我对这次的MyBatis入门又如此的印象深刻,所以才写了这篇东西来介绍一下方法的问题。
接下来,如果你想更加深入又没有别的方法的时候,就可以参考一下其他人的博客或者看书系统的学习一下了。
深入的文章推荐有:
书籍比较少,专门在外面查了一下:
《Java Persistence with MyBatis 3》