Mybatis入门
- u MyBatis概念
- u MyBatis的优点
- u MyBatis与传统JDBC和Hibernate的区别
- u MyBatis的工作流程
- u 创建第一个MyBatis工程
- u 代码的整理及优化
1 Mybatis概念
MyBatis原名叫IBATIS,iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。最初侧重于密码软件的开发,现在是一个基于Java的持久层框架。ibatis本是apache的一个开源项目,2010年这个项目由apache sofeware foundation 迁移到了google code,并且改名为MyBatis。
2 Mybatis优点
2.1 简单性
MyBatis被广泛认为是当今可用的最简单的持久化框架之一。简单性的理念根植于 MyBatis开发团队,它在iBATlS的所有开发目标中居于首位 。 这种简单性的取得是因为 iBATlS直接构建于JDBC和 SQL之上。MyBatis配置文件几乎人人都能读懂,只要有SQL编程的经验。
2.2 生产效率
任何一个优秀的框架,其基本目的都是使得框架的使用者能够获得更高的生产效率.一般情况下,框架负责处理公共的任务,减少编写重复的样板代码,以及解决复杂的架构级的问题。MyBatis在给开发人员带来更高的开发效率方面做得非常成功。在意大利的Java用户组(Java Users Group) 所做的一个案例研究中发现 MyBatis减少了持久层大约62%的代码量。之所以能减少如此多的代码量,究其原因是开发人员再不需要编写繁琐的JDBC代码了。
2.3 性能
性能这个话题无疑会引起框架开发人员、框架使用者以及商业软件开发商之间的一场激烈争论。事实是,从一个较低的层次来看这个问题,无疑所有的框架都会带来一定的性能损失。一般来说,如果你比较硬编码的JDBC代码和 MyBatis代码,做一个 1000000次的 for循环,就会发现JDBC在性能上的确存一些优势。幸运的是,在现代应用程序开发中,以上这样的for循环带来的性能损失并不重要。真正重要的是,你如何从数据库中获取数据,何时获取,获取的频率又是多少。例如,从数据库中动态地获取记录的分页查询,之所以能大大提高应用程序的性能就在于,你不会将潜在的成千上万条记录从数据库中一次取出。同样地,使用像延迟加载这样的特征可以避免加载那些当前用例并不需要的数据。另一方面,如果你确定需要加载一份复杂的对象图,涉及来自多个表的大量数据,那么使用一条SQL语句就完成所有对象的加载显然可以大大提高效率。MyBatis支持许多性能优化措施,我们将在本章的后续章节中详细讨论。就目前而言,最重要的是要知道MyBatis总是能通过一种简单的方式来配置和使用,其性能与JDBC相当,甚至更好。另一个需要重点考虑的问题就是,并不是所有的JDBC代码都是编写良好的。 JDBC API非常复杂,编写正确的代码需要非常小心。不幸的是,大量的JDBC代码都编写得相当糟糕,因此从较低层次上看JDBC甚至还没有 MyBatis工作得好。
2.4 关注分离点
iBATlS通过帮助管理持久化相关的资源来支持应用程序的分层,这些资源包括数据库连接 ( database connection )、预处理语句(prepared statement ) 以及结果集 (resultset)。 iBATlS提供了一组数据库无关的接口以及API ,使得应用程序的其他部分与持久化相关的资源无关。使用 MyBatis,你的代码总是在且按与严格的对象打交道,而不用操心结果集。 MyBatis实际上使得我们更佳接近于应用程序分层这样的最佳实践.
2.5 可移植性
MyBatis是可移植的,由于相对简单的设计,它几乎可以用任何一种语言在任何一个平台上实现。目前,MyBatis支持3种最受欢迎的开发平台 Java、Ruby和微软.NET的C#。
2.6 开源
MyBatis是开源的,因此,对于开发者而言,可以很方便的获取其文档及源代码,并排查使用过程中存在的问题。
3 MyBatis与传统JDBC和Hibernate的区别
3.1 与传统的JDBC进行比较
u 减少了62%的代码量
u 最简单的持久化框架
u 架构级性能增强
u SQL代码从程序代码中彻底分离,可重用
u 增强了项目中的分工
u 增强了移植性
3.2 与Hibernate的比较
Hibernate映射关系如下图,通过映射文件将java对象和数据库表进行映射。
MyBatis映射关系如下图,通过sql语句将java对象和数据表进行连接。
4 MyBatis的工作流程
ORM:Object Relation Mapping:对象关系映射,通俗理解就是将一个对象相关属性和数据库数据进行关联(映射),传统我们对数据库数据的操作可以通过ORM框架转移到对对象的操作上来,这无疑有利于提高程序的开发效率和项目的可维护性,本质是对传统的JDBC操作高级封装。
工作流程:mybatis通过sqlSessionFactory创建sqlSession, sqlSession表示应用程序与数据库的会话,当用户使用mapper.xml文件中配置的的方法时,mybatis首先会解析sql动态标签为对应数据库sql的形式,并将其封装进MapperStatement对象,然后通过executor将sql注入数据库执行,并返回结果。
常见ORM框架:hibernate、mybatis。
5 创建第一个MyBatis工程
- 数据库创建测试表
-- Create table create table STUDENT ( stu_id VARCHAR2(11) not null, stu_name VARCHAR2(50), stu_birthdate DATE, stu_phone VARCHAR2(50)
)
- 新建工程,并引入相关jar包
- 在类路径下创建总配置文件
-
- • SqlMapConfig.xml
- • 配置文件名称其实是任意的
- 在类路径下创建log4j.properties
项目结构:
- 创建pojo类
1 public class Student { 2 3 private String stuId; 4 5 private String stuName; 6 7 private Date stuBirthdate; 8 9 private String stuPhone; 10 11 //省略get/set方法…… 12 13 }
- 创建核心配置文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 5 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 6 7 <configuration> 8 9 <settings> 10 11 <setting name="logImpl" value="LOG4J"/> 12 13 </settings> 14 15 <typeAliases> 16 17 <typeAlias type="cn.mybatis.domain.Student" alias="student" /> 18 19 </typeAliases> 20 21 <environments default="development"> 22 23 <environment id="development"> 24 25 <transactionManager type="JDBC" /> 26 27 <dataSource type="POOLED"> 28 29 <property name="driver" value="oracle.jdbc.OracleDriver" /> 30 31 <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" /> 32 33 <property name="username" value="zhou" /> 34 35 <property name="password" value="123456" /> 36 37 </dataSource> 38 39 </environment> 40 41 </environments> 42 43 <mappers> 44 45 <mapper resource="cn/mybatis/dao/studentMapper.xml" /> 46 47 </mappers> 48 49 </configuration>
- 创建配置Mapper映射文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 5 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 6 7 <mapper namespace="student"> 8 9 <insert id="insertStudent" parameterType="student"> 10 11 insert into student (stu_id,stu_name,stu_birthdate,stu_phone) 12 13 values(#{stuId},#{stuName},#{stuBirthdate},#{stuPhone}) 14 15 </insert> 16 17 </mapper>
- 编写程序读取核心配置文件,调用CRUD功能方法
1 public class Demo_01 { 2 3 private static SqlSessionFactory fac; 4 5 6 7 public static void main(String[] args) throws Exception { 8 9 //获取配置信息 10 11 InputStream is = Resources.getResourceAsStream("SqlMapperConfig.xml"); 12 13 //获取session工厂类 14 15 fac = new SqlSessionFactoryBuilder().build(is); 16 17 //创建要保存的学生信息 18 19 Student s = new Student(); 20 21 s.setStuId("1"); 22 23 s.setStuName("zhou"); 24 25 s.setStuBirthdate(new SimpleDateFormat("yyyy-MM-dd").parse("1990-1-12")); 26 27 s.setStuPhone("341324123"); 28 29 //工厂类的openSession方法获取与数据库的session 30 31 SqlSession sess = fac.openSession(); 32 33 sess.insert("student.insertStudent",s); 34 35 sess.commit(); 36 37 sess.close(); 38 39 } 40 41 }
6 代码的整理及优化
使用分层的思想优化代码:
1 package cn.mybatis.dao; 2 3 import cn.mybatis.domain.Student; 4 5 public interface StudentDao { 6 7 public void insertStudent(Student s); 8 9 } 10 11
1 package cn.mybatis.dao.impl; 2 3 4 5 import org.apache.ibatis.session.SqlSession; 6 7 import org.apache.ibatis.session.SqlSessionFactory; 8 9 10 11 import cn.mybatis.dao.StudentDao; 12 13 import cn.mybatis.domain.Student; 14 15 16 17 public class StudentDaoImpl implements StudentDao{ 18 19 private SqlSessionFactory fac; 20 21 public StudentDaoImpl(SqlSessionFactory fac){ 22 23 this.fac = fac; 24 25 } 26 27 @Override 28 29 public void insertStudent(Student s) { 30 31 SqlSession sess = null; 32 33 try{ 34 35 sess = this.fac.openSession(); 36 37 sess.insert("student.insertStudent", s); 38 39 sess.commit(); 40 41 }catch(Exception e){ 42 43 e.printStackTrace(); 44 45 }finally{ 46 47 sess.close(); 48 49 } 50 51 } 52 53 }
代码的整理及优化:
public class Demo_01 { private static SqlSessionFactory fac; static{ InputStream is = null; try{ //处理并根据config配置文件实例化SqlSessionFactory is = Resources.getResourceAsStream("SqlMapperConfig.xml"); //获取session工厂类 fac = new SqlSessionFactoryBuilder().build(is); }catch(Exception e){ e.printStackTrace(); Logger.getLogger(Demo_01.class).debug(e.getMessage()); } } public static void main(String[] args) throws Exception { //创建要保存的学生信息 Student s = new Student(); s.setStuId("1"); s.setStuName("zhou"); s.setStuBirthdate(new SimpleDateFormat("yyyy-MM-dd").parse("1990-1-12")); s.setStuPhone("341324123"); StudentDao sdao = new StudentDaoImpl(fac); sdao.insertStudent(s); } }