MyBatis简介
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
MyBatis的优缺点
优点:
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
- 解除sql与程序代码的耦合:通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
缺点:
- 编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
- SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
- 框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
- 二级缓存机制不佳
MyBatis如何安装?
如果使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath 中即可。
github下载地址(https://github.com/mybatis/mybatis-3/releases)
如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中:
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>x.x.x</version></dependency>
MyBatis开发流程
1、准备工作
在数据库中建表,并且添加几条数据
将相关jar包导入项目
druid:数据源,替换mybatis自带的数据源(不替换也可以)
log4j:日志
lombok:可以省去写get,set等冗长的方法(详细看
关于lombok.jar的使用_橘子恶霸、的博客-CSDN博客
)
mybatis:mybaris(必须)
mysql-connector:mysql驱动(必须)
2、创建实体类与dao层
Book.java:
package com.dyit.entity;
import java.io.Serializable;
import java.util.Date;
import org.apache.ibatis.type.Alias;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Alias("Book")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book implements Serializable{
private Integer id;
private String isbn;//出版编号
private String title;//书籍名称
private String author;//作者
private String cover;//封面
private Double price;//价格
private Date date;//出版日期
}
说明:@Alias(“Book”)为类的别名
IBookMapper.java
package com.dyit.mapper;
import org.apache.ibatis.annotations.Param;
import com.dyit.entity.Book;
public interface IBookMapper {
//添加树
void updateAuthorOrPrice(@Param("id")int id,@Param("price")Double price,@Param("author")String author);
//通过id查找书
Book findById(@Param("id") int id);
}
说明:@Param(注解绑定参数)
3、数据库配置信息
在src\resource\druid下创建druid.properties(使用的是druid数据源)
druid.driver = com.mysql.cj.jdbc.Driver
druid.url = jdbc:mysql://localhost:3306/mybatis_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
druid.username=root
druid.password=123456
按照自己的数据库配置
4、创建并编写MyBatis配置文件(mybatis-config.xml)
在src/resource/config下创建mybatis-config.xml
mybatis-config.xml初始模板:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置标签的顺序:(properties?, settings?, typeAliases?,
typeHandlers?, objectFactory?, objectWrapperFactory?,
reflectorFactory?, plugins?, environments?,
databaseIdProvider?, mappers?)-->
</configuration>
配置相关信息
<?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>
<!-- 读取数据源配置文件 -->
<properties resource="resource/druid/druid.properties"/>
<!-- 读取实体类别名 -->
<typeAliases>
<package name="com.dyit.entity"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!-- 配置数据库事务管理 -->
<dataSource type="com.dyit.util.MybatisDataSource"><!-- 读取数据源信息 -->
<property name="driverClassName" value="${druid.driver}"/>
<property name="url" value="${druid.url}"/>
<property name="username" value="${druid.username}"/>
<property name="password" value="${druid.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载xxx.mapper.xml -->
<mappers>
<mapper resource="resource/mapper/Book.mapper.xml"/>
</mappers>
</configuration>
在environments标签项中配置相关信息,default属性和id属性可根据自己意愿填写(其实就是个名字而已),我们在这选用的不是是MyBatis默认的连接池,使用dataSource 标签的type属性读取druid
5、日志配置
在src下创建log4j.properties配置日志信息
log4j.rootLogger=debug,stdout,logfile
#console output
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.appender.stdout.PatternLayout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}<-->%F<-->%p<-->%m%n
#file output
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=D:/logs/log.log
log4j.appender.logfile.layout=org.apache.log4j.SimpleLayout
log4j.appender.logfile.PatternLayout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}<-->%F<-->%p<-->%m%n
#mybatis log
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
6、配置xxx.mapper.xml
IBookMapper.java中的抽象方法,如何去实现它们呢?
这就要靠我们的Mapper配置文件了,一个Dao接口文件对应一个Mapper配置文件。MyBatis替我们封装了数据访问的其他操作,我们只需要关注Sql语句本身就可以了,而Sql语句写在哪呢?就是Mappe配置文件中。
在src\resource\mapper下创建Book.mapper.xml
下面是Mapper文件的初始模板:
<?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.dao.UserDao">
</mapper>
<?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.dyit.mapper.IBookMapper">
<cache/><!-- 开启二级缓存 -->
<resultMap type="Book" id="BookMap">
<id property="id" column="book_id"/>
<result property="isbn" column="book_isbn"/>
<result property="title" column="book_title"/>
<result property="author" column="book_author"/>
<result property="price" column="book_price"/>
<result property="cover" column="book_cover"/>
<result property="date" column="book_date"/>
</resultMap>
<insert id="save">
INSERT INTO book_tab(book_isbn,book_title,book_author,book_date,book_price,book_cover)
VALUES(#{isbn},#{title},#{author},#{date},#{price},#{cover})
</insert>
<select id="findById" resultMap="BookMap">
SELECT * FROM book_tab WHERE book_id = #{id}
</select>
</mapper>
resultMap 标签就是属性关系映射,来解决字段名不一致的问题,当我们需要用的时候,将select标签的resultType属性改为resultMap就可以了。
7、编写测试类
新建个test包创建单元测试
package test;
import com.dyit.entity.*;
import java.io.IOException;
import java.io.Reader;
import java.util.Date;
import java.util.List;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.dyit.mapper.IBookMapper;
public class TestMybatis {
private SqlSession sqlSession;
@Before
public void before() throws IOException {
//读取mybatis-config.xml获取一个字符流
Reader in = Resources.getResourceAsReader("resource/config/mybatis-config.xml");
//通过字符流获取sqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//拿到sqlSession
sqlSession = sqlSessionFactory.openSession();
}
@After
public void after() {
//事务提交,关闭资源
sqlSession.commit();
sqlSession.close();
}
@Test
public void testsave() throws IOException {
IBookMapper mapper = sqlSession.getMapper(IBookMapper.class);
Book book = new Book(null,"dyit-03","c#入门","张三","java.png",77.00,new Date());
mapper.save(book);
}
@Test
public void testfindById() throws IOException {
IBookMapper mapper = sqlSession.getMapper(IBookMapper.class);
Book book = mapper.findById(1);
System.out.println(book.toString());
}
}
savetest()测试结果
testfindById()测试结果
MyBatis的工作原理以及核心流程介绍
原文:(http://www.mybatis.cn/archives/706.html)
MyBatis的底层操作封装了JDBC的API,MyBatis的工作原理以及核心流程与JDBC的使用步骤一脉相承,MyBatis的核心对象(SqlSession,Executor)与JDBC的核心对象(Connection,Statement)相互对应。本文的核心观点是:从JDBC入手并立足于JDBC,才能深入的理解MyBatis的工作原理以及核心流程。
1、如何掌握MyBatis的工作原理?
关于MyBatis的工作原理,网上的文章是汗牛充栋,但是站长觉得,要结合JDBC来理解MyBatis的工作原理往往才能更透彻。我们知道,JDBC有四个核心对象:
(1)DriverManager,用于注册数据库连接
(2)Connection,与数据库连接对象
(3)Statement/PrepareStatement,操作数据库SQL语句的对象
(4)ResultSet,结果集或一张虚拟表
而MyBatis也有四大核心对象:
(1)SqlSession对象,该对象中包含了执行SQL语句的所有方法【1】。类似于JDBC里面的Connection 【2】。
(2)Executor接口,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。
(3)MappedStatement对象,该对象是对映射SQL的封装,用于存储要映射的SQL语句的id、参数等信息。
(4)ResultHandler对象,用于对返回的结果进行处理,最终得到自己想要的数据格式或类型。可以自定义返回类型。
2、MyBatis的工作原理以及核心流程详解
MyBatis的工作原理如下图所示:
上面中流程就是MyBatis内部核心流程,每一步流程的详细说明如下文所述:
(1)读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。
(2)加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
(3)构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。
(4)创建会话对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。
(5)Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
(6)MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。
(7)输入参数映射。输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。
(8)输出结果映射。输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。
备注
备注【1】的说明如下:
在JDBC中,Connection不直接执行SQL方法,而是利用Statement或者PrepareStatement来执行方法。
在使用JDBC建立了连接之后,可以使用Connection接口的createStatement()方法来获取Statement对象,也可以调用prepareStatement()方法获得PrepareStatement对象,通过executeUpdate()方法来执行SQL语句。
而在MyBatis中,SqlSession对象包含了执行SQL语句的所有方法。但是它是委托Executor执行的。
从某种意义上来看,MyBatis里面的SqlSession类似于JDBC中的Connection,他们都是委托给其他类去执行。
最后说一点,虽然SqlSession对象包含了执行SQL语句的所有方法,但是它同样包括了:
<T> T getMapper(Class<T> type);
所以SqlSession也可以委托给映射器来执行数据的增删改查操作。如下代码所示:
// 获得mapper接口的代理对象
PersonMapper pm = session.getMapper(PersonMapper.class);
// 直接调用接口的方法,查询id为1的Peson数据
Person p2 = pm.selectPersonById(1);
这上面来看,SqlSession是不是也类似于JDBC中的Connection呢。