Mybatis 简介
- MyBatis 是一款优秀的持久层框架。
- MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程。
- MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类【Plain Old Java Objects,普通的 Java对象】映射成数据库中的记录。
- MyBatis 本是apache的一个开源项目 ibatis,2010 年这个项目由 apache 迁移到了google code,并且改名为 MyBatis 。
- 2013年11月迁移到 Github。
持久化
持久化是将程序数据在持久状态和瞬时状态间转换的机制。
-
即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。
-
例如:JDBC是一种持久化机制。文件IO也是一种持久化机制。
为什么需要持久化服务呢?由于内存本身的缺陷引起的
- 内存断电后数据会丢失,但有一些对象是无论如何都不能丢失的,比如银行账号等,遗憾的是,人们还无法保证内存永不掉电。
- 内存过于昂贵,与硬盘、光盘等外存相比,内存的价格要高2~3个数量级,而且维持成本也高,至少需要一直供电。所以即使对象不需要永久保存,也会因为内存的容量限制不能一直呆在内存中,需要持久化来缓存到外存。
持久层
- 完成持久化工作的代码块 . ----> dao层 【DAO (Data Access Object) 数据访问对象】
- 大多数情况下特别是企业级应用,数据持久化往往也就意味着将内存中的数据保存到磁盘上加以固化,而持久化的实现过程则大多通过各种关系数据库来完成。
- 不过这里有一个字需要特别强调,也就是所谓的“层”。对于应用系统而言,数据持久功能大多是必不可少的组成部分。也就是说,我们的系统中,已经天然的具备了“持久层”概念?也许是,但也许实际情况并非如此。之所以要独立出一个“持久层”的概念,而不是“持久模块”、“持久单元”,也就意味着,我们的系统架构中,应该有一个相对独立的逻辑层面,专注于数据持久化逻辑的实现。
- 与系统其他部分相对而言,这个层面应该具有一个较为清晰和严格的逻辑边界。【说白了就是用来操作数据库存在的!】
为什么需要 MyBatis
-
MyBatis就是帮助程序猿将数据存入数据库中 , 和从数据库中取数据。
-
传统的 jdbc 操作 , 有很多重复代码块。比如 : 数据取出时的封装,数据库的建立连接等等...,通过框架可以减少重复代码,提高开发效率。
-
MyBatis 是一个半自动化的 ORM 框架 (Object Relationship Mapping) -->对象关系映射
-
所有的事情,不用Mybatis依旧可以做到,只是用了它,所有实现会更加简单!
-
MyBatis的优点
-
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件就可以了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供xml标签,支持编写动态sql。
- .......
-
最重要的一点,使用的人多!公司需要!
Mybatis 入门程序
搭建环境-->导入MyBatis--->编写代码--->测试
1. 搭建数据库
CREATE DATABASE mybatis;
USE mybatis;
DROP TABLE IF EXISTS USER;
CREATE TABLE USER(
id INT(20) NOT NULL PRIMARY KEY,
NAME VARCHAR(30) DEFAULT NULL,
pwd VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO USER(id, NAME, pwd) VALUES
(1, '张三', '123456'),
(2, '李四', 'abcdef'),
(3, '王五', '000000');
2. 导入MyBatis
要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。
如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:
-
创建 Maven 父工程,删除 src文件夹,在 pom.xml 文件中导入依赖(Mybatis、MySql、junit);
-
在父工程中创建子模块,这样所有子工程可以直接使用这个父工程中的依赖 jar 包。
<!-- 导入依赖 -->
<dependencies>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
3. 编写 MyBatis 核心配置文件(mybatis-config.xml)
在 src.main.resources 文件夹下创建 mybatis-config.xml 文件,该配置文件包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。
这里目前只对 driver、url、username、password 的 value 进行了修改填写。一定要填写正确!!!
注意:一定要在此文件中注册 Mapper.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 核心配置文件 -->
<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/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 每一个 Mapper.XML 都需要在 Mybatis 核心配置文件中注册!!-->
<mappers>
<mapper resource="com/song/dao/UserMapper.xml"/>
</mappers>
</configuration>
4. 编写 MyBatis 工具类
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
通过 SqlSessionFactory 获得 SqlSession 对象实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
使用工具类实现可以避免重复的操作。
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 java.io.IOException;
import java.io.InputStream;
// SqlSessionFactory --> sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory; // 提升作用域
static {
try {
// 使用Mybatis第一步:获取 SqlSessionFactory 对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e){
e.printStackTrace();
}
}
// 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
public static SqlSession getSqlSession(){
// SqlSession sqlSession = sqlSessionFactory.openSession();
// return sqlSession;
return sqlSessionFactory.openSession();
}
}
5. 创建实体类
构造和数据库中的表相对应的实体类:
public class User {
private int id; //id
private String name; //姓名
private String pwd; //密码
//构造,有参,无参
//set/get
//toString()
}
6. 编写 UserDao(Mapper) 接口
import com.song.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
}
7. 编写 UserMapper.xml 文件
这个 xml 配置文件实现的功能与之前的 UserDao 接口的实现类(UserDaoImpl)一致。
UserMapper.xml 文件和 UserDao 接口在同一个包中。
- namespace 绑定一个对应的 Dao/Mapper 接口
- select 表示是查询语句,其中: id 绑定方法名;resultType 绑定返回类型,一定要写全限定类名,因为配置文件不会像 Java 类一样会自动找关联,如果返回值是集合,都写泛型中的类
<?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">
<!--namespace = 绑定一个对应的 Dao/Mapper 接口-->
<mapper namespace="com.song.dao.UserDao">
<!-- select 查询语句,id 绑定方法名,
返回结果写全限定类名,因为配置文件不会像java类一样会自动找关联,集合都写泛型中的类-->
<select id="getUserList" resultType="com.song.pojo.User">
select * from mybatis.user
</select>
</mapper>
8. 编写测试类
-
使用 Junit 包测试,这个测试类放在 test 下面和要测试的类的包级结构对应的位置。
-
官方文档建议手动加上 try/catch… 语句,但是实际上并不需要。
-
有两种方法通过 sqlSession 执行 SQL 命令,但是第二种是旧版本中使用的,现在不推荐使用,第一种更加简洁,使用和指定语句的参数和返回值相匹配的接口(比如 UserDao.class),代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。
import com.song.pojo.User;
import com.song.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
// 第一步:获取 sqlSession 对象,使用工具类
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
// 方式一:执行 sql,通过 getMapper
// 获取 userDao 对象
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
// 方式二:不推荐使用(已经进行了强制类型转换)
// List<User> userList = sqlSession.selectList("com.song.dao.UserDao.getUserList");
for (User user : userList){
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
// 关闭 sqlSession
sqlSession.close();
}
}
}
遇到的问题
- 编写 MyBatis 核心配置文件(mybatis-config.xml)时,一定要注册 Mapper 配置文件
<!-- 每一个Mapper.XML 都需要在 Mybatis 核心配置文件中注册!!-->
<mappers>
<mapper resource="com/song/dao/UserMapper.xml"/>
</mappers>
-
Maven 导出时静态资源过滤问题(如果不配置的话,XML 文件会被过滤掉)
maven 由于它的约定大于配置,所以可能遇到写的配置文件,无法被导出或者生效的问题,解决方案是在 pom.xml 文件中配置 resources,保险起见,在父工程和子工程的 pom 文件中都配置一下。
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
参考
Mybatis 官方文档:http://www.mybatis.org/mybatis-3/zh/index.html