mybatis入门
1.概述
因为觉得自己写的概念信息未必比别人好,而且这些理论知识了解就好,内核信息还是要看源码。所以从相对权威的百度百科转载了基本信息,也因此它的真实性是经过检验的。
1.1 什么是 MyBatis?
1.1.1 基本信息
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。 iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs) 截止到本篇博客发表日期(2019-04-22),最新版本是MyBatis 3.5.1 ,其发布时间是2019年4月8日。1.1.2 官方描述
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis官方提供的 入门学习地址:http://www.mybatis.org/mybatis-3/zh/index.html
项目发布在GitHub上:https://github.com/mybatis/mybatis-3/tree/master/src/site
1.1.3 背景介绍
MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。 每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。 用xml文件构建SqlSessionFactory实例是非常简单的事情。推荐在这个配置中使用类路径资源(classpath resource),但你可以使用任何Reader实例,包括用文件路径或file://开头的url创建的实例。MyBatis有一个实用类----Resources,它有很多方法,可以方便地从类路径及其它位置加载资源。 持久层框架示意图:1.1.4 特点
-
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
1.1.5 框架架构
(1)加载配置:配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
(2)SQL解析:当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(可以是Map、JavaBean或者基本数据类型),Mybatis会根据SQL的ID找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的SQL语句和参数。 (3)SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。 (4)结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。 1.1.6 功能架构
我们把Mybatis的功能架构分为三层: (1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。 (2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。 (3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。 1.1.7 动态SQL MyBatis 最强大的特性之一就是它的动态语句功能。如果您以前有使用JDBC或者类似框架的经历,您就会明白把SQL语句条件连接在一起是多么的痛苦,要确保不能忘记空格或者不要在columns列后面省略一个逗号等。动态语句能够完全解决掉这些痛苦。
尽管与动态SQL一起工作不是在开一个party,但是MyBatis确实能通过在任何映射SQL语句中使用强大的动态SQL来改进这些状况。动态SQL元素对于任何使用过JSTL或者类似于XML之类的文本处理器的人来说,都是非常熟悉的。 在上一版本中,需要了解和学习非常多的元素,但在MyBatis 3 中有了许多的改进,现在只剩下差不多二分之一的元素。MyBatis使用了基于强大的OGNL表达式来消除了大部分元素。 1.1.8 总体流程 (1)加载配置并初始化 触发条件:加载配置文件 处理过程:将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。 (2)接收调用请求 触发条件:调用Mybatis提供的API 传入参数:为SQL的ID和传入参数对象 处理过程:将请求传递给下层的请求处理层进行处理。 (3)处理操作请求 触发条件:API接口层传递请求过来 传入参数:为SQL的ID和传入参数对象 处理过程: (A)根据SQL的ID查找对应的MappedStatement对象。 (B)根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。 (C)获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。 (D)根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。 (E)释放连接资源。 (4)返回处理结果将最终的处理结果返回。 2.入门示例 2.1 XML配置示例 2.1.1 XML配置示例流程简述 2.1.1.1 示例流程简述
第一步:导入包(任何框架需要的事情):mybatis的支撑包和数据库的JDBC支撑包
第二步:创建总配置文件,文件名随便写,(如果使用properties文件作为数据库对象的信息文件,则先建立一个对应的db.properties文件)
第三步:创建一个MybatisUtils工具类,(获得操作对象)
第四步:创建一个映射接口
第五步:创建一个映射文件
第六步:在总配置文件加载映射文件。
第七步:编写测试代码
2.1.1.2 mybatis官方推荐到的工程目录架构
/my_application /bin /devlib /lib <-- MyBatis *.jar 文件在这里。 /src /org/myapp/ /action /data <-- MyBatis 配置文件在这里, 包括映射器类, XML 配置, XML 映射文件。 /mybatis-config.xml /BlogMapper.java /BlogMapper.xml /model /service /view /properties <-- 在你 XML 中配置的属性文件在这里。 /test /org/myapp/ /action /data /model /service /view /properties /web /WEB-INF /web.xml
2.1.1.3 我的工程目录架构
2.1.2 操作示例
2.1.2.1 导入包 /MybatisDemo/lib
(A) mybatis框架支撑包 mybatis-3.4.1.jar
下载地址:http://www.mybatis.cn/82.html
(B) MYSQL数据库JDBC支撑包 mysql-connector-java-5.1.47.jar
下载地址:http://dev.mysql.com/downloads/connector/ >> Connector/J >> 选择对应版本 >>到这就不需要我说了吧
我这里使用的是mysql数据库,所以导入的是mysql的JDBC支撑包
2.1.2.2 创建db.properties数据库链接信息文件/MybatisDemo/src/db.properties
db.driver=org.gjt.mm.mysql.Driver db.url=jdbc:mysql://localhost:3306/mybatisdb db.username=root db.password=123456
2.1.2.3 创建mybatis主配置文件xxx.XML 文件名自便,示例:/MybatisDemo/src/mybatis.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" > <configuration> <!-- 指定properties配置文件的路径 --> <properties resource="db.properties"></properties> <!-- 配置数据库连接 --> <!-- environments:环境集,可以在里面配置多个environment,一个environment对应一个数据库连接 mybatis支持配置多个数据库连接,但是只能执行一个 default属性:作用就是指定默认执行的数据库连接environment标签的id属性 --> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <!-- dataSource:配置数据源 typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class); typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class); typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
JNDI:使用JNDI的数据源,就是在WEB服务器配置一个数据库连接池,如再TOMCAT里面配置一个数据源。就是JNDI数据源 POOLED:使用数据库连接池,Mybatis内置默认有一个简单的内置连接池 UNPOOLED:不使用数据库连接,直接使用数据库JDBC直连 --> <dataSource type="POOLED"> <!-- 驱动 --> <property name="driver" value="${db.driver}"/> <!-- 连接字符串 --> <property name="url" value="${db.url}"/> <!-- 用户名 --> <property name="username" value="${db.username}"/> <!-- 密码 --> <property name="password" value="${db.password}"/> </dataSource> </environment> </environments> </configuration>
2.1.2.4 创建一个MybatisUtils工具类/MybatisDemo/src/cn/slm/util/MybatisUtils.java
package cn.slm.util; import java.io.IOException; import java.io.Reader; 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 MybatisUtils { // 注意:基于如果出现多个会话工厂,可能导致事务不同步的问题,所以我们一个项目只使用一个会话工厂 public static final SqlSessionFactory SSF = createSqlSessionFactory(); private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>(); // 1.获得会话工厂 private static SqlSessionFactory createSqlSessionFactory() { try { Reader reader = Resources.getResourceAsReader("mybatis.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sessionFactory = builder.build(reader); return sessionFactory; } catch (IOException e) { e.printStackTrace(); } return null; } // 2.获得操作对象,SqlSession对象 public static SqlSession getSqlSession() {
//单例模式 确保sqlSession对象的唯一性有效性 if (threadLocal.get() == null) { SqlSession session = SSF.openSession(); threadLocal.set(session); } return threadLocal.get(); } }
2.1.2.5 创建一个映射接口/MybatisDemo/src/cn/slm/mapper/StudentMapper.java
package cn.slm.mapper; import cn.slm.pojo.Student; public interface StudentMapper { // 需求:实现插入数据到student表 // 注意:如果是增删改操作,返回的类型必须是int类型 // 返回的是操作影响的行数。 int insert(Student student); }
2.1.2.6 创建一个映射文件/MybatisDemo/src/cn/slm/mapper/xml/StudentMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" > <!-- 注意事项:使用映射接口的配置方式,namespace必须指向接口的类全名 --> <mapper namespace="cn.slm.mapper.StudentMapper"> <!-- useGeneratedKeys:作用打开支持ID回填,设置为true keyColumn:设置ID回填,ID对象数据库的字段名 keyProperty:设置ID回填到JavaBean对应的属性名 --> <insert id="insert" useGeneratedKeys="true" keyColumn="stu_id" keyProperty="stuId" > <!-- 注意:如果传递过来的是一个JavaBean对象,那么设置的属性名为,set方法对应的属性名。如:setStuName 对应的是 stuName --> INSERT INTO tb_student (stu_name, stu_age, stu_password) VALUES (#{stuName}, #{stuAge}, #{stuPassword}) </insert> </mapper>
2.1.2.7 在总配置文件加载映射文件 /MybatisDemo/src/mybatis.xml
<!-- 加载映射文件 如果是多个,则添加多个相应的 mapper--> <mappers> <mapper resource="cn/slm/mapper/xml/StudentMapper.xml"/> </mappers>
完整xml文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" > <configuration> <!-- 指定数据库配置文件的路径 --> <properties resource="db.properties"></properties> <!-- 配置数据库连接 --> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${db.driver}"/> <property name="url" value="${db.url}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </dataSource> </environment> </environments> <!-- 加载映射文件 --> <mappers> <mapper resource="cn/slm/mapper/xml/StudentMapper.xml"/> </mappers> </configuration>
2.1.2.8 编写测试代码
package cn.slm.test; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import cn.slm.mapper.StudentMapper; import cn.slm.pojo.Student; import cn.slm.util.MybatisUtils; public class MybatisTest { @Test public void insert(){ //1.获得操作对象,session SqlSession session = MybatisUtils.getSqlSession();
//2.获得操作接口的动态对象 StudentMapper studentMapper = session.getMapper(StudentMapper.class); Student student=new Student(); student.setStuName("陈七");
//3.插入对象 int count = studentMapper.insert(student);
//4.提交事务 session.commit();
//5.关闭 session.close();
//6.打印返回值 System.out.println("数据库库受影响记录数:"+count); System.out.println("ID:"+student.getStuId()); } }
2.1.2.9 测试结果
2.1.2.9.1 junit执行情况:
2.1.2.9.2 控制台打印的返回值
2.1.2.9.3 数据库中表的更新