一MyBatis 简介

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、添加依赖
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<!-- mybatis相关依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
3、创建数据库和表,针对MySQL数据库
SQL脚本如下:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号', `username` varchar(20) NOT NULL COMMENT '用户名', `password` varchar(10) NOT NULL COMMENT '密码', `name` varchar(20) NOT NULL COMMENT '姓名', `email` varchar(50) DEFAULT NULL COMMENT '邮箱', `state` varchar(50) DEFAULT NULL COMMENT '国家', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
表中的数据如下:

2.3、定义操作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.dinghuoqin.dao.studentMapper"就是com.dinghuoqin.dao(包名)+studentMapper(studentMapper.xml文件去除后缀)
-->
<mapper namespace="com.dinghuoqin.dao.studentMapper">
<!-- 在select标签中编写查询的SQL语句, 设置select标签的id属性为selectStudentById,id属性值必须是唯一的,不能够重复
使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型
resultType="com.dinghuoqin.vo.message"就表示将查询结果封装成一个message类的对象返回
message类就是message表所对应的实体类
-->
<!--查询-->
<!--查询所有数据-->
<select id="selectStudent" resultType="com.dinghuoqin.vo.message">
select id,username,password,name,email,state from user
</select>
<!--根据id查询数据-->
<select id="selectStudentById" resultType="com.dinghuoqin.vo.message">
select id,username,password,name,email,state from user where id = #{id}
</select>
<!--根据姓名模糊查询数据-->
<select id="selectStudentByName" resultType="com.dinghuoqin.vo.message">
select id,username,password,name,email,state from user where name like '%${value}%';
</select>
<!--分页查询-->
<select id="selectStudentFY" resultType="com.dinghuoqin.vo.message" parameterType="java.lang.Integer">
select id,username,password,name,email,state from user limit #{page},#{number};
</select>
<!--根据id删除数据-->
<delete id="deleteStudentById" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<!--
添加数据
parameterType:指定输入的参数类型是pojo(包括用户信息);
#{}中指定pojo的属性名称,接收到pojo对象的属性值 ,mybatis通过OGNL(类似struts2的OGNL)获取对象的属性值
useGeneratedKeys="true" keyProperty="id"
-->
<insert id="insertStudent" parameterType="com.dinghuoqin.vo.message" >
<!--
将insert插入的数据的主键返回到User对象中;
select last_insert_id():得到刚insert进去记录的主键值,只适用于自增主键;
keyProperty:将查询到的主键值,设置到parameterType指定的对象的那个属性
order:select last_insert_id()执行顺序,相对于insert语句来说它的执行顺序。
resultType:指定select last_insert_id()的结果类型;
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer" >
SELECT LAST_INSERT_ID() AS id;
</selectKey>
insert into user(username,password,name,email,state) values(#{username},#{password},#{name},#{email},#{state});
</insert>
<!--根据id修改数据修改-->
<update id="updateStudent" parameterType="com.dinghuoqin.vo.message">
update user set username=#{username},password=#{password},name=#{name},email=#{email},state=#{state} where id=#{id}
</update>
</mapper>
解释

参考:https://www.cnblogs.com/hellokitty1/p/5216025.html
2.4、添加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"/> <!--加载驱动:com.mysql.jdbc.Driver-->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_01_user"/> <!--数据库名称:mybatis_01_user-->
<property name="username" value="root"/> <!--用户名-->
<property name="password" value=""/> <!--密码-->
</dataSource>
</environment>
</environments>
<mappers>
<!-- 注册studentMapper.xml文件studentMapper.xml位于mapper这个目录下,所以resource写成mapper/studentMapper.xml-->
<mapper resource="mapper/studentMapper.xml"/>
</mappers>
</configuration>
解释

2.5、定义表所对应的实体类
message实体类的代码如下:

package com.dinghuoqin.vo;
public class message {
int id;
String username;
String password;
String name;
String email;
String state;
@Override
public String toString() {
return "message{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", email='" + email + '\'' +
", state='" + state + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public message(int id, String username, String password, String name, String email, String state) {
this.id = id;
this.username = username;
this.password = password;
this.name = name;
this.email = email;
this.state = state;
}
public message(String username, String password, String name, String email, String state) {
this.username = username;
this.password = password;
this.name = name;
this.email = email;
this.state = state;
}
public message() {
}
}
会话工具类:
package utils;
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;
public class MyBatisUtil {
/**
* 获得会话工厂
* */
public static SqlSessionFactory getFactory(){
InputStream inputStream = null;
SqlSessionFactory sqlSessionFactory=null;
try{
//加载conf.xml配置文件,转换成输入流
inputStream = SqlSessionFactory.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();
}
}
}
2.6、编写数据访问类
StudentDao.java,执行定义的select语句
package com.dinghuoqin.Dao;
import com.dinghuoqin.Daoport.StudentDaoI;
import com.dinghuoqin.vo.message;
import org.apache.ibatis.session.SqlSession;
import utils.MyBatisUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class StudentDao implements StudentDaoI {
SqlSession session = MyBatisUtil.openSession(true);
/**
* 根据编号查询数据
*/
public message sel(int id){
message entity=session.selectOne("com.dinghuoqin.dao.studentMapper.selectStudentById",id);
return entity;
}
/**
* 根据姓名模糊查询数据
*/
public List<message> sels(String name){
List<message> list=session.selectList("com.dinghuoqin.dao.studentMapper.selectStudentByName",name);
return list;
}
/**
* 查询所有数据
*/
public List<message> sel(){
List<message> list=session.selectList("com.dinghuoqin.dao.studentMapper.selectStudent");
return list;
}
/**
* 分页查询
*/
public List<message> selFy(int x,int y){
int i=(x-1)*y;
Map<String,Integer> map=new HashMap<String, Integer>();
map.put("page",i);
map.put("number",y);
List<message> list=session.selectList("com.dinghuoqin.dao.studentMapper.selectStudentFY",map);
return list;
}
/**
* 根据id删除数据
*/
public int delete(int id){
int i=session.delete("com.dinghuoqin.dao.studentMapper.deleteStudentById",id);
session.commit();
return i;
}
/**
* 添加数据
*/
public int insert(message m){
session.insert("com.dinghuoqin.dao.studentMapper.insertStudent",m);
session.commit();
return m.getId();
}
/**
* 根据id修改数据
*/
public int update(message m){
int i=session.update("com.dinghuoqin.dao.studentMapper.updateStudent",m);
session.commit();//数据库操作同步
return i;
}
//
public static void main(String[] args){
Scanner S=new Scanner(System.in);
System.out.print("请输入用户名:");
int name=S.nextInt();
StudentDao dao = new StudentDao();
message m=dao.sel(name);
System.out.println(m);
}
}
执行过程解释:

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
单元测试:
package test;
import com.dinghuoqin.Dao.StudentDao;
import com.dinghuoqin.vo.message;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
public class StudentDaoTest {
@Before
public void before() throws Exception {
}
@After
public void after() throws Exception {
}
/**
*
* Method: sel(int id)
*
*/
StudentDao dao =new StudentDao();
@Test
public void testSelId() throws Exception {
//TODO: Test goes here...
System.out.println(dao.sel(2));
}
/**
*
* Method: sels(String name)
*
*/
@Test
public void testSels() throws Exception {
//TODO: Test goes here...
System.out.println(dao.sels("小"));
}
/**
*
* Method: sel()
*
*/
@Test
public void testSel() throws Exception {
//TODO: Test goes here...
System.out.println(dao.sel());
}
/**
*
* Method: delete(int id)
*
*/
@Test
public void testDelete() throws Exception {
//TODO: Test goes here...
System.out.println(dao.delete(2));
}
/**
*
* Method: insert(message m)
*
*/
@Test
public void testInsert() throws Exception {
//TODO: Test goes here...
message m=new message("丁鑫","123456","丁钦","1234567@qq.com","中国");
System.out.println(dao.insert(m));
System.out.println("用户编号:"+m.getId());
}
/**
*
* Method: update(message m)
*
*/
@Test
public void testUpdate() throws Exception {
//TODO: Test goes here...
message m=new message(2,"阿萨德","123456","撒旦王","1234567@qq.com","日本");
System.out.println(dao.insert(m));
}
@Test
public void testSelFy() throws Exception{
List<message> m=dao.selFy(2,3);
for (message M:m) {
System.out.println(M);
}
}
}
测试结果:

667

被折叠的 条评论
为什么被折叠?



