MyBatis入门与实例

框架

框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。可以说,一个框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供上下文(Context)关系。——百度百科

对于程序员来说,框架是一套资源,这套资源中会包含 Jar 包、文档,还有些会包含源码、代码示例等。这套资源从相关的官网上可以下载。一般是以压缩文件的形式出现。

Mybatis 概述

MyBatis 本是 apache 的一个开源项目 iBatis, 2010 年这个项目由 apache 迁移到了 google,并更名为 MyBatis。 2013 年迁移到 Github。——百度百科《MyBatis》

Mybatis 简介

MyBatis 是一个优秀的基于 Java 的持久层框架,它内部封装了 JDBC,使开发者只需关注 SQL 语句本身,而不用再花费精力去处理诸如注册驱动、创建 Connection、 配置 Statement
等繁杂过程。

Mybatis 通过 xml 或注解的方式将要执行的各种 statement (statement、preparedStatement 等)配置起来,并通过 Java 对象和 Statement 中 SQL 的动态参数进行映射生成最终执行的 SQL 语句,最后由 MyBatis 框架执行 SQL 并将结果映射成 Java 对象并返回。

Mybatis 与 Hibernate

Hibernate 框架是提供了全面的数据库封装机制的“全自动” ORM,即实现了 POJO 和数据库表之间的映射,以及 SQL 的自动生成和执行。

相对于此, MyBatis 只能算作是“半自动” ORM。其着力点,是在 POJO 类 与 SQL 语句之间的映射关系。也就是说, MyBatis 并不会为程序员自动生成 SQL 语句。具体的 SQL 需要程序员自己编写,然后通过 SQL 语句映射文件,将 SQL 所需的参数,以及返回的结果字段映射到指定 POJO。因此, MyBatis 成为了“全自动” ORM 的一种有益补充。

与 Hibernate 相比, MyBatis 具有以下几个特点:

  • 在 XML 文件中配置 SQL 语句,实现了 SQL 语句与代码的分离,给程序的维护带来
    了很大便利。
  • 因为需要程序员自己去编写 SQL 语句,程序员可以结合数据库自身的特点灵活控
    制 SQL 语句,因此能够实现比 Hibernate 等全自动 ORM 框架更高的查询效率,能够完成复
    杂查询。
  • 简单,易于学习,易于使用,上手快。

Mybatis 体系结构

{% asset_img mybatis01.png %}

Mybatis 工作原理

{% asset_img mybatis02.jpg %}

第一个 Mybatis 程序

需求: 实现将 Student 信息写入到 DB 中。

基本程序

1. 导入 Jar 包

除了需要导入 MyBatis 的核心 Jar 包及依赖 Jar 包外,还需要导入 MySQL 的驱动 Jar 包,JUnit 测试的 Jar 包。

在这里插入图片描述

2.定义实体类

package com.huang.beans;

public class Student {
	private Integer id;
	private String name;
	private int age;
	private double score;
	
	public Student(String name, int age, double score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getScore() {
		return score;
	}
	public void setScore(double score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	

}

3. 在 DB 中生成表结构,即创建空表

{% asset_img mybatis03.jpg %}

注意:
由于后面要创建的 MyBatis 映射文件映射的是 SQL 语句,而非像 Hibernate 一样,是类到表,属性到字段的映射。所以, MyBatis 要求, 在创建数据库表时,字段名要与属性名一致,如果不一致,需要通过 resultMap 解决。

4. 定义 Dao 接口

package com.huang.dao;

import com.huang.beans.Student;

public interface IStudentDao {
	void insertStu(Student student);

}

5. 定义映射文件

映射文件,简称为 mapper,主要完成 Dao 层中 SQL 语句的映射。映射文件名随意,一般放在 dao 包中。 这里映射文件名称定为 mapper.xml。

映射文件的约束文件常用有两种:.dtd、.xsd,约束文件 mybatis-3-mapper.dtd 文件,在 MyBatis 的核心 Jar 包的 org.apache.ibatis.builder.xml 包中存放。当然,主配置文件的约束 dtd 文件也在该位置存放。

映射文件内容为:

<?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="test">
	<insert id="insertStudent"
	parameterType="com.huang.beans.Student">
		insert into student(name,age,score) 
		values(#{name},#{age}, #{score})
	</insert>
</mapper>

注意:
#{ }中写入的是 Student 类的属性名。

6. 定义主配置文件

在主配置文件中添加约束,即配置文件头,配置文件名也可以随意命名,这里命名为 mybatis.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="onlineEM">
		<environment id="onlineEM">
			<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="123456"/>
			</dataSource>
		</environment>
		<environment id="testEM">
			<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="123456"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 注册映射文件 -->
	<mappers>
		<mapper resource="com/huang/dao/mapper.xml"/>
	</mappers>
	
</configuration>

7. 定义 Dao 实现类

package com.huang.dao;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.huang.beans.Student;

public class StudentDaoImpl implements IStudentDao {
	
	private SqlSession sqlSession;

	@Override
	public void insertStu(Student student) {
		try {
			//1.读取主配置文件
			InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
			//2.创建SqlSessionFactory对象
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
			//创建SqlSession对象
			sqlSession = sqlSessionFactory.openSession();
			//操作
			sqlSession.insert("insertStudent",student);
			//SqlSession提交
			sqlSession.commit();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//SqlSession关闭,添加了close()不用作事务回滚
			if (sqlSession != null) {
				sqlSession.close();
				
			}
		}
		
	}

}

8. 定义测试类

package com.huang.test;

import org.junit.Before;
import org.junit.Test;

import com.huang.beans.Student;
import com.huang.dao.StudentDaoImpl;

public class MyTest {
	private StudentDaoImpl dao;
	
	@Before
	public void before() {
		dao= new StudentDaoImpl();
	}
	@Test
	public void test01() {
		Student student = new Student("赵六", 26, 97.5);
		dao.insertStu(student);
	}

}

9. 添加日志控制文件

MyBatis 使用 Log4j 进行日志处理,而 Login4j2 对其支持并不好,所以在 MyBatis 中需要将 log4j.properties 放入到项目的 src 目录下。

若将日志级别设置为 debug,则可以显示出所执行的 SQL 语句、参数值、对 DB 的影响条数等信息。若将级别设置为 trace,则还可显示出查询出的每条记录的每个字段名及值。

在这里插入图片描述

注意:
若日志对象使用根日志对象 rootLogger,则会输出太多的信息。在 MyBatis 中,可以指定要输出日志的工作空间 namespace 的名字。此时,只会输出该 namespace 下执行的 SQL 的日志内容。

##define a logger
log4j.logger.test=debug,console

10. 运行结果

{% asset_img mybatis04.jpg %}

使用工具类

由于每一次执行 SqlSession 的方法,均需首先获取到该对象。而 SqlSession 对象的获取又相对比较繁琐,所以,可以将获取 SqlSession 对象定义为一个工具类方法。

SqlSession 对象是通过 SqlSessionFactory 对象创建的。由于 SqlSessionFactory 类为重量级对象,且为线程安全的,所以可以将 SqlSessionFactory 对象定义为单例的。

1. 创建工具类

package com.huang.dao;

import java.io.IOException;
import java.io.InputStream;

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 MyBatisUtil {
	private static SqlSessionFactory factory;
	public static SqlSession getSqlSession() {
		try {
			
			if (factory == null) {
				//读取主配置文件
				InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
				//创建SqlSession工厂
				factory = new SqlSessionFactoryBuilder().build(inputStream);
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return factory.openSession();
	}

}

2. 修改 Dao 接口的实现类

package com.huang.dao;

import org.apache.ibatis.session.SqlSession;

import com.huang.beans.Student;

public class StudentDaoImpl implements IStudentDao {
	
	private SqlSession sqlSession;

	@Override
	public void insertStu(Student student) {
		try {
			sqlSession = MyBatisUtil.getSqlSession();
			//操作
			sqlSession.insert("insertStudent",student);
			//SqlSession提交
			sqlSession.commit();
		} finally {
			//SqlSession关闭,添加了close()不用作事务回滚
			if (sqlSession != null) 
				sqlSession.close();
			
		}
		
	}

}

从属性文件中读取 DB 连接四要素

为了方便对数据库连接的管理, DB 连接四要素数据一般都是存放在一个专门的属性文件中的。 MyBatis 主配置文件需要从这个属性文件中读取这些数据。

1. 定义属性文件

在 src 下定义属性文件 jdbc.properties。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.user=root
jdbc.password=123456

2. 修改主配置文件

对主配置文件,第一,需要注册属性文件。第二,需要从属性文件中通过 key,将其 value 读取出来。

<!-- 注册属性文件 -->
    <properties resource="jdbc.properties"/>

主配置文件详解

主配置文件名可以随意命名,其主要完成以下几个功能:
(1)注册存放 DB 连接四要素的属性文件;
(2)注册实体类的全限定性类名的别名;
(3)配置 MyBatis 运行环境,即数据源与事务管理器;
(4)注册映射文件。

注册 DB 连接四要素属性文件

<!-- 注册DB连接四要素属性文件 -->
	<properties resource="jdbc.properties"/>

指定实体类全限定性类名的别名

对于实体类的全限定性类名的别名指定方式,一般使用方式。这样做的好处是会将该包中所有实体类的简单类名指定为别名,写法简单方便。

<!-- 定义类型别名 -->
	<typeAliases>
		<!-- 将指定包中所有类的简单类名当作其别名 -->
		<package name="com.huang.beans"/>
	</typeAliases>

不过,还有另外的指定方式:通过指定。

<typeAliases>
	    <typeAlias type="com.huang.beans.Student" alias="Student"/>
	</typeAliases>
  • type:全限定性类名
  • alias:别名

该方式的好处是,可以指定别名为简单类名以外的其它名称。当然,弊端是,必须逐个指定,比较繁琐。

另外,Mybatis 还提供了内置的类型别名:

基本类型:

别名 类型 别名 类型
int int integer int
_short short _long long
_double double _float float
byte byte boolean boolean

常用包类型别名:

别名 类型 别名 类型
string String byte Byte
long Long short Short
int Integer integer Integer
double Double float Float
boolean Boolean date Date
object Object collection Collection
list List arraylist ArrayList
map Map hashmap HashMap
iterator Iterator

配置 MyBatis 的运行环境

配置 MyBatis 的运行环境,主要是配置数据源与事务管理器。

1. <environments/>标签

<!-- 指定默认运行环境 -->
	<environments default="onlineEM">
	<!-- 项目上线环境 -->
		<environment id="onlineEM">
		</environment>
		
		<!-- 项目测试环境 -->
		<environment id="testEM">
		</environment>
	</environments>

在 <environments/> 中可包含多个运行环境 <environment/>,但其 default 属性指定了当前 MyBatis 运行时所选择使用的环境。<environment/> 的 id 属性为当前定义的运行环境的名称,可以任意命名。该名称会作为 <environments/> 的 default 属性的值出现。

2. <transactionManager/> 标签

<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC"/>

该标签用于指定 MyBatis 所使用的事务管理器。 MyBatis 支持两种事务管理器类型: JDBC 与 MANAGED。

  • JDBC:使用 JDBC 的事务管理机制。即,通过 Connection 的 commit()方法提交,通过 rollback() 方法回滚。但默认情况下, MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对事务进行提交或回滚。从日志的输出信息中可以看到。
  • MANAGED:由容器来管理事务的整个生命周期(如 Spring 容器)。
  1. <dataSource/> 标签
    该标签用于配置 MyBatis 使用的数据源类型与数据库连接基本属性。常见有类型有: UNPOOLED、 POOLED、 JDNI 等。
  • UNPOOLED :不使用连接池。即每次请求,都会为其创建一个 DB 连接,使用完毕后,会马上将此连接关闭。
  • POOLED:使用数据库连接池来维护连接。
  • JNDI:数据源可以定义到应用的外部,通过 JNDI 容器获取数据库连接。
<!-- 数据库连接池 -->
<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="123456"/>
</dataSource>

若要从属性文件中读取 DB 连接四要素信息,则使用如下方式:

			
<!-- 数据库连接池 -->
<dataSource type="POOLED">
	<property name="driver" value="${jdbc.driverClassName}"/>
	<property name="url" value="${jdbc.url}"/>
	<property name="username" value="${jdbc.user}"/>
	<property name="password" value="${jdbc.password}"/>
</dataSource>

指定映射文件

指定映射文件的方式有多种。但所有的方式,都是指定在 <mappers/> 标签中的。

<mapper resource=””/> 指定映射文件

若映射文件只有一个,则可直接使用如下形式:

<!-- 注册映射文件 -->
	<mappers>
		<mapper resource="com/huang/dao/mapper.xml"/>
	</mappers>

若映射文件有多个,则可使用如下形式:

<!-- 注册映射文件 -->
	<mappers>
		<mapper resource="com/huang/dao/mapper.xml"/>
		<mapper resource="com/huang/dao/mapper2.xml"/>
	</mappers>

API 详解

Dao 中需要通过 SqlSession 对象来操作 DB。而 SqlSession 对象的建,需要其工厂对象 SqlSessionFactory。 SqlSessionFactory 对象,需要通过其构建器对象 SqlSessionFactoryBuilder 的 build()方法,在加载了主配置文件的输入流对象后创建。

Resources 类

Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象。

SqlSessionFactoryBuilder 类

SqlSessionFactory 的创建,需要使用 SqlSessionFactoryBuilder 对象的 build() 方法。由于 SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁。所以,一般会将该 SqlSessionFactoryBuilder 对象创建为一个方法内的局部对象,方法结束,对象销毁。

SqlSessionFactory 接口

SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的, 所以一个应用只需要一个该对象即可。 创建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession() 方法。

  • openSession(true):创建一个有自动提交功能的 SqlSession
  • openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交
  • openSession():同 openSession(false)

SqlSession 接口

SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以 SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。

SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close() 方法,将其关闭。再次需要会话,再次创建。 而在关闭时会判断当前的 SqlSession 是否被提交:若没有被提交,则会执行回滚后关闭;若已被提交,则直接将 SqlSession 关闭。所以, SqlSession 无需手工回滚。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章