Mybatis01-MyBatis快速入门
Posted hl0516
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis01-MyBatis快速入门相关的知识,希望对你有一定的参考价值。
一、MyBatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
1.1、 MyBatis 的特点
简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只有两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
灵活:mybatis不会对应用程序或者数据库的现有设计加强任何影响。sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
提供映射标签,支持对象与数据库的ORM字段关系映射
提供对象关系映射标签,支持对象关系组建维护
提供XML标签,支持编写动态sql。
1.2、MyBatis工作流程
(1)、加载配置并初始化
触发条件:加载配置文件
配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将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)、返回处理结果将最终的处理结果返回。
无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点:
在java对象和数据库之间有做mapping的配置文件,也通常是xml 文件
从配置文件(通常是XML配置文件中)得到 SessionFactory
由SessionFactory 产生 Session
在Session中完成对数据的增删改查和事务提交等
在用完之后关闭Session
1.3、MyBatis架构
Mybatis的功能架构分为三层:
API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
1.4、MyBatis的主要成员如层次结构
主要成员:
Configuration:MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中
SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能
Executor:MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
StatementHandler:封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等
ParameterHandler:负责对用户传递的参数转换成JDBC Statement 所对应的数据类型
ResultSetHandler:负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
TypeHandler:负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换
MappedStatement:MappedStatement维护一条<select|update|delete|insert>节点的封装
SqlSource:负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
BoundSql:表示动态生成的SQL语句以及相应的参数信息
层次结构:
1.5、学习资源
mybatis3中文帮助:http://www.mybatis.org/mybatis-3/zh/index.html
mybatis-spring:http://www.mybatis.org/spring/zh/index.html
MyBatis中国分站:http://www.mybatis.cn/
源代码:https://github.com/mybatis/mybatis-3/
二、MyBatis 快速入门示例
2.1、在IDEA中创建项目
普通java项目或者是Maven项目都可以,如下图所示:
2.2、添加依赖
下载地址:https://github.com/mybatis/mybatis-3/releases
【MyBatis】
mybatis-3.4.6.jar
【MYSQL驱动包】
mysql-connector-java-5.1.38-bin.jar
Maven POM
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.hmy.mybatis02</groupId> <artifactId>Mybatis02</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--MyBatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--MySql数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!-- JUnit单元测试工具 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies> </project>
3、创建数据库和表,针对MySQL数据库
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL, `sex` enum(\'boy\',\'girl\',\'secret\') DEFAULT \'secret\', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
将SQL脚本在MySQL数据库中执行,完成创建数据库和表的操作,如下:
表中的数据如下:
2.3、添加Mybatis配置文件
在Resources目录下创建一个conf.xml文件,如下图所示:
conf.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="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/ssm"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/studentMapper.xml"/> </mappers> </configuration>
解释
2.4、定义表所对应的实体类
Student实体类的代码如下:
package com.hanlu.mybatis02.entities; public class Student { private int id; private String name; private String sex; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "Student{" + "id=" + id + ", name=\'" + name + \'\\\'\' + ", sex=\'" + sex + \'\\\'\' + \'}\'; } }
2.5、定义操作Student表的sql映射文件
在resources目录下创建一个mapper目录,专门用于存放sql映射文件,在目录中创建一个studentMapper.xml文件,如下图所示:
studentMapper.xml文件的内容如下:
<?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,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的 例如namespace="com.hanlu.mybatis02.dao.studentMapper"就是com.hanlu.mybatis02.dao(包名)+studentMapper(studentMapper.xml文件去除后缀) --> <mapper namespace="com.hanlu.mybatis02.dao.studentMapper"> <!-- 在select标签中编写查询的SQL语句, 设置select标签的id属性为selectStudentById,id属性值必须是唯一的,不能够重复 使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型 resultType="com.hanlu.mybatis02.entities.Student"就表示将查询结果封装成一个Student类的对象返回 Student类就是student表所对应的实体类 --> <!-- 根据id查询得到一个user对象 --> <select id="selectStudentById" resultType="com.hanlu.mybatis02.entities.Student"> select * from student where id = #{id} </select> </mapper>
解释
参考:https://www.cnblogs.com/hellokitty1/p/5216025.html
2.6、在配置文件中注册映射文件
在配置文件conf.xml中注册studentMapper.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="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/ssm"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!-- 注册studentMapper.xml文件studentMapper.xml位于mapper这个目录下,所以resource写成mapper/studentMapper.xml--> <mapper resource="mapper/studentMapper.xml"/> </mappers> </configuration>
2.7、编写数据访问类
StudentDao.java,执行定义的select语句
package com.hanlu.mybatis02.dao; import com.hanlu.mybatis02.entities.Student; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class StudentDao { public Student getStudentById(int id){ //使用类加载器加载mybatis的配置文件(它也加载关联的映射文件) InputStream stream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml"); //构建sqlSession的工厂 SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(stream); //使用MyBatis提供的Resources类加载mybatis的配置文件(它也加载关联的映射文件) //Reader reader = Resources.getResourceAsReader(resource); //构建sqlSession的工厂 //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //创建能执行映射文件中sql的sqlSession SqlSession session=ssf.openSession(); /** * 映射sql的标识字符串, * com.hanlu.mybatis02.dao.studentMapper是studentMapper.xml文件中mapper标签的namespace属性的值, * selectStudentById是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL */ Student student=session.selectOne("com.hanlu.mybatis02.dao.studentMapper.selectStudentById",1); return student; } public static void main(String[] args) { StudentDao dao=new StudentDao(); Student student=dao.getStudentById(1); System.out.println(student); } }
执行过程解释:
1、mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
参考:https://www.cnblogs.com/selene/p/4604605.html
2.8、编写单元测试
import com.hanlu.mybatis02.dao.StudentDao; import com.hanlu.mybatis02.entities.Student; import org.junit.Test; import org.junit.Before; import org.junit.After; public class StudentDaoTest { @Before public void before() throws Exception { } @After public void after() throws Exception { } /** * Method: getStudentById(int id) */ @Test public void testGetStudentById() throws Exception { StudentDao dao=new StudentDao(); Student student=dao.getStudentById(1); System.out.println(student); } }
测试结果:
2.9、IDEA中Junit插件与生成测试类位置
打开IntelliJ IDEA工具,Alt+Ctrl+S,打开设置窗口,点击进入Plugins。
从插件资源库中搜索JunitGenerator V2.0版本
安装此插件,重启IDEA就可以了。
现在可通过此工具自动完成test类的生成了,在需要进行单元测试的类中按 Alt+Insert
选中你要创建测试用例的方法即可。
IntelliJ IDEA JUnit Generator自动创建测试用例到指定test目录
1.打开File->Settings
2.搜索junit,找到JUnit Generator
3.Properties选项卡里的Output Path为测试用例生成的目录,修改为test目录:
SOURCEPATH/../../test/java/SOURCEPATH/../../test/java/{PACKAGE}/${FILENAME}
4.切换到JUnit 4选项卡,可以修改生成测试用例的模板,比如类名、包名等
修改生成位置:
修改模板文件:
测试类生成目录分析:
${SOURCEPATH}/test/${PACKAGE}/${FILENAME} $SOURCEPATH/../../test/java/{PACKAGE}/${FILENAME} |
对应的目录结构为
${SOURCEPATH}是到src/main/java这一层
../是退到上一层目录的意思,对着图理解一下
三、基于XML映射实现完整数据访问
MyBatis可以使用XML或注解作为映射器的描述,XML强大且可以解偶,注解方便且简单。
因为每一个操作都需要先拿到会话,这里先定义一个工具类以便复用:
会话工具类:
package com.hanlu.mybatis02.utils; import com.hanlu.mybatis02.dao.StudentDao; import com.hanlu.mybatis02.entities.Student; 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; /** * @author HMY * @date 2018/10/17-17:07 */ /** * MyBatis 会话工具类 * */ public class SqlSessionFactoryUtil { /** * 获得会话工厂 * * */ public static SqlSessionFactory getFactory(){ InputStream inputStream=null; SqlSessionFactory sqlSessionFactory=null; try { //加载conf.xml配置文件,转换成输入流 inputStream= StudentDao.class.getClassLoader().getResourceAsStream("conf.xml"); //根据配置文件的输入流构造一个SQL会话工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); }finally { if (inputStream!=null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return sqlSessionFactory; } /** * 获得sql会话,是否自动提交 * */ public static SqlSession openSession(boolean isAutoCommit){ return getFactory().openSession(isAutoCommit); } /** * 关闭会话 * */ public static void closeSession(SqlSession session){ if (session!=null){ session.close(); } } }
XML映射器studentMapper:
<?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.hanlu.mybatis02.studentMapper"> <select id="selectStudentById" resultType="student"> select id,name,sex from student where id = #{id} </select> <select id="selectStudentByName" parameterType="String" resultType="Student"> select id,name,sex from student where name LIKE \'%${value}%\' </select> <insert id="insertStudent" parameterType="student"> insert into student(name,sex) values (#{name},#{sex}) </insert> <update id="updateStudent" parameterType="student"> UPDATE student SET name=#{name},sex=#{sex} WHERE id=#{id} </update> <delete id="deleteStudent" parameterType="int"> DELETE FROM student WHERE id=#{id} </delete> </mapper>
数据访问类StudentDao.java:
package com.hanlu.mybatis02.dao; import com.hanlu.mybatis02.entities.Student; import com.hanlu.mybatis02.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; import java.util.List; /** * @author HMY * @date 2018/10/17-10:20 */ public class StudentDao implements StudentMapper { public Student selectStudentById(int id) { Student entity = null; /* //加载conf.xml配置文件,转换成输入流 InputStream inputStream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml"); //根据配置文件的输入流构造一个SQL会话工厂 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); //打开一个会话 SqlSession session = sqlSessionFactory.openSession();*/ //打开一个会话 SqlSession session = SqlSessionFactoryUtil.openSession(true); //查询单个对象 entity = session.selectOne("com.hanlu.mybatis02.studentMapper.selectStudentById", id); //关闭会话 SqlSessionFactoryUtil.closeSession(session); return entity; } public List<Student> selectStudentByName(String name) { /*InputStream inputStream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml"); SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); SqlSession session=sqlSessionFactory.openSession();*/ SqlSession session = SqlSessionFactoryUtil.openSession(true); List<Student> list = session.selectList("com.hanlu.mybatis02.studentMapper.selectStudentByName", name); SqlSessionFactoryUtil.closeSession(session); return list; } public int insertStudent(Student student) { int rows = 0; SqlSession session = SqlSessionFactoryUtil.openSession(true); rows = session.insert("com.hanlu.mybatis02.studentMapper.insertStudent", student); SqlSessionFactoryUtil.closeSession(session); return rows; } public int updateStudent(Student student) { int rows = 0; SqlSession session = SqlSessionFactoryUtil.openSession(true); rows = session.update("com.hanlu.mybatis02.studentMapper.updateStudent", student); SqlSessionFactoryUtil.closeSession(session); return rows; } public int deleteStudent(int id) { int rows = 0; SqlSession session = SqlSessionFactoryUtil.openSession(true); rows = session.delete("com.hanlu.mybatis02.studentMapper.updateStudent", id); SqlSessionFactoryUtil.closeSession(session); return rows; } }
单元测试:
package com.hanlu.mybatis02.dao; import com.hanlu.mybatis02.entities.Student; import org.junit.Assert; import org.junit.Test; import org.junit.Before; import org.junit.After; import java.util.List; /** * StudentDao Tester. * * @author <Authors name> * @since <pre>ʮ�� 17, 2018</pre> * @version 1.0 */ public class StudentDaoTest { StudentDao dao; @Before public void before() throws Exception { dao=new StudentDao(); } @After public void after() throws Exception { } /** * * Method: selectStudentById(int id) * */ @Test public void testSelectStudentById() throws Exception { //TODO: Test goes here... } /** * * Method: selectStudentByName(String name) * */ @Test public void testSelectStudentByName() throws Exception { List<Student> list=dao.selectStudentByName("i"); System.out.println(list); Assert.assertNotNull(list); } @Test public void testInsertStudent() throws Exception { Student student=new Student(); student.setName("玛丽"); student.setSex("girl"mybatis复习Mybatis-Plus:快速开始(SpringBoot + Mybatis + Mybatis)
Mybatis-Plus:快速开始(Spring + Mybatis + Mabatis-Plus)
Mybatis-Plus:了解Mybatis-Plus快速开始(Mybatis + Mybatis-Plus,Mybatis-Plus自动做了属性映射)