1. 简介

Java程序都是通过JDBC连接数据库,但是只定义了接口规范,具体的实现交给各个数据库厂商去实现,因为每个数据库都有其特殊性。所以JDBC是一种桥接模式

这里为什么说JDBC是一种桥接模式呢?为例避免JDBC的缺陷出现了ORM模型,比如Hibernate,提供的是一种全表映射模型。因为Hibernate的一些缺陷,比如:

  • Hibernate屏蔽了SQL,只能全表映射,更新时需要发送所有的字段
  • 无法根据不同的条件组装不同的SQL
  • 对多表关联和复杂SQL查询支持较差,需要自己写SQL,返回后,需要自己将数据组装为POJO
  • 不能有效地支持存储过程
  • 虽然有HQL,但是性能较差。

因此出现了MyBatis,一个半自动的框架。之所以称之为半自动,是因为它需要手动提供POJO、SQL和映射关系,而全表映射的Hibernate只需要提供POJO和映射关系即可,因为Hibernate无需编写SQL,所以开发效率优于MyBatis。

2. MyBatis入门

MyBatis的核心组件:

  • SqlSessionFactoryBuilder(构造器):它会根据配置信息或者代码来生成SqlSessionFactory(工厂接口)
  • SqlSessionFactory:依靠工厂来生成SqlSession
  • SqlSession:是一个既可以发送SQL去执行并返回结果,也可以获取Mapper的接口
  • SQL Mapper:它是MyBatis新设计的组件,是由一个java接口和XML文件(或注解)构成的,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。

2.1 构建SqlSessionFactory

每个MyBatis的应用都是以SqlSessionFactory的实例为中心,可以通过SqlSessionFactoryBuilder获得,注意SqlSessionFactory是一个工厂接口而不是实现类,其任务是创建SqlSession。SqlSession类似于一个JDBC的Connection对象。MyBatis提供了两种模式去创建SqlSessionFactory:一种是XML配置的方式,另一种是代码方式。要尽量的使用配置文件,这样一方面可以避免硬编码,一方面方便日后配置人员修改。

org.apache.ibatis.session.Configuration在MyBatis中将以一个Configuration类对象的形式存在,存在于整个MyBatis应用的生命期中,以便重复读取和运用。我们可以一次性解析一次配置的XML保存到Configuration对象中。在MyBatis中提供了两个SqlSessionFactory的实现类,DefaultSqlSessionFactory和SqlSessionManager。目前使用的是DefaultSqlSessionFactory。

2.1.1 使用XML方式构建

这里以一个简易的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>
<!--定义别名 -->
<typeAliases>
<typeAlias alias="role" type="com.learn.chapter2.po.Role"/>
</typeAliases>
<!--定义数据库信息,默认使用development数据库构建环境-->
<environments default="development">
<environment id="development">
<!--采用jdbc事务管理 -->
<transactionManager type="JDBC">
<property name="autoCommit" value="false"/>
</transactionManager>
<!--配置数据库链接信息 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!--定义映射器 -->
<mappers>
<mapper resource="com/learn/chapter2/mapper/roleMapper.xml"/>
</mappers>
</configuration>

然后用代码实现创建SqlSessionFactory:

String resource="mybatis-config.xml";
InputStream inputStream=null;
inputStream=Resources.getResourceAsStream(resource);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);

这里创建了一个XML文件输入流,用SqlSessionFactoryBuilder读取XML的信息 来创建SqlSessionFactory的对象。MyBatis的解析程序会将mybatis-config.xml文件配置信息解析到Configuration类对象里面,然后利用SqlSessionFactoryBuilder读取这个对象,为我们创建SqlSessionFactory。

2.1.2 使用代码方式构建

不推荐这种方式,因为修改环境的时候,要重新编译代码,不利于维护。

     //构建数据库连接池
PooledDataSource dataSource=new PooledDataSource();
dataSource.setDriver("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
dataSource.setUsername("root");
dataSource.setPassword("root");
//构建数据库事务方式
TransactionFactory transactionFactory=new JdbcTransactionFactory();
//创建数据库运行环境
Environment environment=new Environment("development",transactionFactory,dataSource);
//构建Configuration对象
Configuration configuration=new Configuration(environment);
//注册一个MyBatis上下文别名
configuration.getTypeAliasRegistry().registerAlias("role",Role.class);
//加入一个映射器
configuration.addMapper(RoleMapper.class);
//使用SqlSessionFactoryBuilder构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(configuration);
return sqlSessionFactory;

采用代码方式一般是需要加入自己特性的时候才会用到,例如数据源配置的信息要求是加密的时候,我们需要把它转化出来。大部分情况下不建议用这个方式来创建SqlSessionFactory

2.1.2 创建SqlSession

在MyBatis中SqlSession接口的实现类有两个,分别是DefaultSqlSession和SqlSessionManager。我们构建了SqlSessionFactory,然后生成门面接口SqlSession。SqlSession接口类似于一个JDBC中的Connection接口对象,我们需要保证每次用完正确关闭它。

SqlSession的用途主要是获取映射器以及直接通过命名信息去执行SQL返回结果。

2.1.3 映射器

由Java接口和XML文件(或注解)共同组成,作用如下:

  • 定义参数类型
  • 描述缓存
  • 描述SQL语句
  • 定义查询结果和POJO的映射关系

使用XML文件配置方式实现Mapper,第一步给出Java接口:

public interface RoleMapper {
public Role getRole(Long id);
public int deleteRole(Long id);
public int insertRole(Role role);
}

第二步给出一个映射文件:

<?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.learn.chapter2.mapper.RoleMapper">
<select id="getRole" resultType="role" parameterType="long">
select id,role_name as roleName,note from t_role where id=#{id}
</select>
</mapper>
  • MyBatis会读取这个配置文件,生成映射器
  • 定义一个命名空间为com.learn.chapter2.mapper.RoleMapper的SQL Mapper,这个命名空间和我们定义的接口的全限定名要一致
  • 用一个select元素定义一个查询SQL,id是getRole,和我们接口中的方法名是一致的
  • #{id}为这条SQL的参数。而SQL列的别名和POJO的属性名称保持一致。那么MyBatis就会把这条语句查询的结果自动映射到我们需要的POJO属性上

现在可以使用SqlSession来获取这个Mapper:

RoleMapper roleMapper=sqlSession.getMapper(RoleMapper.class);
Role role=roleMapper.getRole(1L);

2.1.4 Java注解方式实现Mapper

不推荐注解的方式,如果系统简单的话,使用注解方式也不失为一个好办法。

注册这个接口为映射器:

2.1.4 一些疑问

这要注意的是在MyBatis中保留这iBatis,通过命名空间+SQL id 的方式发送SQL并返回数据的形式,而不需要获取映射器:

2.2 生命周期

SqlSessionFactoryBuilder:只存在于方法的局部,作用是生成SessionFactory对象。

SqlSessionFactory:存在于MyBatis应用的整个生命周期中,唯一责任是创建SqlSession,要采用单例模式。

SqlSession:一个会话,相当于JDBC的一个Connection对象,他的生命周期应该是在请求数据库处理事务的过程中。它是一个线程不安全的对象。

Mapper:一个接口,没有任何实现类,作用是发送SQL。因此它应该在一个SqlSession事务方法之内,是一个方法级别的东西。

2.3 实例

代码清单2-11:log4j.properties

log4j.rootLogger=DEBUG, stdout
log4j.logger.org=BEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: m%n

其中参数的解释见博文:http://www.cnblogs.com/alipayhutu/archive/2012/06/21/2558249.html

其次,构建SessionFactory,我们需要配置文件,代码:

<?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>
<!--定义别名 -->
<typeAliases>
<typeAlias alias="role" type="com.learn.chapter2.po.Role"/>
</typeAliases>
<!--定义数据库信息,默认使用development数据库构建环境-->
<environments default="development">
<environment id="development">
<!--采用jdbc事务管理 -->
<transactionManager type="JDBC">
<property name="autoCommit" value="false"/>
</transactionManager>
<!--配置数据库链接信息 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!--定义映射器 -->
<mappers>
<mapper resource="com/learn/chapter2/mapper/roleMapper.xml"/>
</mappers>
</configuration>

构建SqlSessionFactory

package com.learn.chapter2.util;

import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger; import org.apache.commons.logging.Log;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class SqlSessionFactoryUtil {
//SqlSessionFactory对象
private static SqlSessionFactory sqlSessionFactory=null;
//类线程锁
private static final Class Class_LOCK=SqlSessionFactoryUtil.class;
/**
* 私有化构造参数
*/
private SqlSessionFactoryUtil(){} /**
* 构建SqlSessionFactory
*/
public static SqlSessionFactory initSqlSessionFactory(){
String resource="mybatis-config.xml";
InputStream inputStream=null;
try{
inputStream=Resources.getResourceAsStream(resource);
}catch (Exception e) {
Logger.getLogger(SqlSessionFactoryUtil.class.getName()).log(Level.SEVERE, null,e);
}
synchronized (Class_LOCK) {
if(sqlSessionFactory==null){
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
}
return sqlSessionFactory;
}
/**
* 打开SqlSession
*/
public static SqlSession openSqlSession(){
if(sqlSessionFactory==null){
initSqlSessionFactory();
}
return sqlSessionFactory.openSession();
}
}

上面要注意的部分:

1. 类线程锁:private static final Class Class_LOCK=SqlSessionFactoryUtil.class;

实现一个POJO类——Role.java

package com.learn.chapter2.po;

public class Role {
private Long id;
private String roleName;
private String note;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}

还需要一个映射器的描述:

<?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.learn.chapter2.mapper.RoleMapper">
<select id="getRole" resultType="role" parameterType="long">
select id,role_name as roleName,note from t_role where id=#{id}
</select>
<insert id="insertRole" parameterType="role">
insert into t_role(role_name,note) values (#{roleName},#{note})
</insert>
<delete id="deleteRole" parameterType="long">
delete from t_role where id=#{id}
</delete>
</mapper>

定义相应的接口:

package com.learn.chapter2.mapper;

import com.learn.chapter2.po.Role;

public interface RoleMapper {
public Role getRole(Long id);
public int deleteRole(Long id);
public int insertRole(Role role);
}

使用一个main方法来测试:

package com.learn.chapter2.main;

import org.apache.ibatis.session.SqlSession;

import com.learn.chapter2.mapper.RoleMapper;
import com.learn.chapter2.po.Role;
import com.learn.chapter2.util.SqlSessionFactoryUtil; public class Chapter2Main {
public static void main(String[] args){
SqlSession sqlSession=null;
try{
sqlSession=SqlSessionFactoryUtil.openSqlSession();
RoleMapper roleMapper=sqlSession.getMapper(RoleMapper.class);
Role role=new Role();
role.setRoleName("testName");
role.setNote("testRole");
roleMapper.insertRole(role);
roleMapper.deleteRole(1L);
sqlSession.commit();
}catch (Exception e) {
System.err.println(e.getMessage());
sqlSession.rollback();
}finally{
if(sqlSession!=null){
sqlSession.close();
}
}
}
}

《深入浅出MyBatis技术原理与实战》——1.简介,2.入门的更多相关文章

  1. 《深入浅出MyBatis技术原理与实战》——6. MyBatis的解析和运行原理

    MyBatis的运行分为两大部分,第一部分是读取配置文件缓存到Configuration对象,用以创建SqlSessionFactory,第二部分是SqlSession的执行过程. 6.1 涉及的技术 ...

  2. 《深入浅出MyBatis技术原理与实战》——7. 插件

    在第6章讨论了四大运行对象的运行过程,在Configuration对象的创建方法里我们看到了MyBatis用责任链去封装它们. 7.1 插件接口 在MyBatis中使用插件,我们必须使用接口Inter ...

  3. 《深入浅出MyBatis技术原理与实战》——4. 映射器,5. 动态SQL

    4.1 映射器的主要元素 4.2 select元素 4.2.2 简易数据类型的例子 例如,我们需要统计一个姓氏的用户数量.应该把姓氏作为参数传递,而将结果设置为整型返回给调用者,如: 4.2.3 自动 ...

  4. 深入浅出MyBatis技术原理与实战

    第1 章 MyBatis 简介..................................................................................... ...

  5. 《深入浅出MyBatis技术原理与实战》——3. 配置

    要注意的是上面那些层次是不能够颠倒顺序的,否则MyBatis在解析文件的时候就会出现异常. 3.1 properties元素 properties是一个属性配置元素,让我们能在配置文件的上下文中使用它 ...

  6. 深入浅出Mybatis技术原理与实战(杨开振)(带详细书签) PDF 下载 高清 完整版+源码

    (杨开振) 源码 IDE eclipse 建表语句也在里面 电子书+源码地址

  7. 2017.2.9 深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二)-----配置文件详解

    深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二) ------配置文件详解 8.2 MyBatis-Spring应用 8.2.1 概述 本文主要讲述通过注解配置MyBa ...

  8. 2MyBatis入门--深入浅出MyBatis技术原理与实践(笔记)

    什么是 MyBatis ? MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...

  9. 3MyBatis配置--深入浅出MyBatis技术原理与实践(笔记)

    XML 映射配置文件 configuration 配置 properties 属性 settings 设置 typeAliases 类型命名 typeHandlers 类型处理器 objectFact ...

随机推荐

  1. Spring源码解析-Advice中的Adapter模式

    在spring中与通知相关的类有: 以Advice结尾的通知接口    MethodBeforeAdvice    AfterReturningAdvice   ThrowsAdvice 以Inter ...

  2. ACE反应器(Reactor)模式(2)

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/18/595808.html 在Socket编程中,常见的事件就是"读就绪" ...

  3. 常州模拟赛d7t3 水管

    分析:第一问还是很好做的,关键是怎么做第二问.我们可以每次删掉最小生成树上的一条边,然后再求一次最小生成树,看边权和大小和原来的是不是一样的,不过这个做法效率很低. 考虑Kruskal算法的原理,每次 ...

  4. 【链表】在O(1)的时间删除链表的节点

    /** * 在O(1)的时间删除链表的节点 * * @author * */ public class Solution { public static void deleteNode(Node he ...

  5. HDU多校(Distinct Values)

    Problem Description Chiaki has an array of n positive integers. You are told some facts about the ar ...

  6. 中频IF

    Intermediate 频率是指中频. 一般RF射频有三个频率,基带频率,中频,射频. 射频是发射到空中的频率,也就是我们一般说的2.4G, Sub-1G.但这个频率太高,不利于放大器做增益控制.所 ...

  7. php 生成压缩文件

    $fileList = array( "site_upload/form_file_clause_extend/20180224/1519456901_1481718257.jpg" ...

  8. floor ceil

    echo floor(11/10); echo ceil(11/10); swiper  可以用在ajax的success中,如果用ejs拼接的,放ajax里面才可以轮播

  9. php环境的安装

    一.xampp的安装 1.下载xampp安装包. 2.next下一步傻瓜式的安装. 3.输入地址127.0.0.1进入如下页面. 二.LAMP环境的安装

  10. HDU5875 Function

    题意:给定序列,有m个区间的询问,求每个询问a[l]%a[l+1]...%a[r]后的值.(N<=10^5) 思路:这题如果使用线段树,可能会由于姿势和卡常数原因TLE,由于数据好像比较奇怪(? ...