mybatis原是Apache的一个开源项目iBatis,2010年6月这个项目由Apache Software Foundation 迁移到了 Google Code,随着开发团队转投Google Code 旗下, iBatis3.x正式更名为MyBatis。是 一个基于Java的持久层框架。 iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。
1.Mybatis是一款优秀的(数据)持久层框架,它支持定制化的SQL、存储过程以及高级映射。
2.Mybatis避免了几乎所有的JDBC代码手动获取参数以及结果集。
3.Mybatis可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的POJO(Plain Old Java Objects,普通的java对象)映射成数据库的记录,是一种ORM(Object Relational Mapping,对象关系映射)实现。
4.Mybatis将基本的JDBC常用接口封装,对外提供操作即可。
5.Mybatis中文官网:https://mybatis.org/mybatis-3/zh/getting-started.html
我们首先来回顾一下传统JDBC编程的步骤:
1.加载数据库驱动(Mysql8的方式)
Class.forName("com.mysql.cj.jdbc.Driver");//利用反射机制加载Driver类,给的是类的地址
2.创建并获取数据库链接
String url = "jdbc:mysql://127.0.0.1:3306/school_db?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC";
Connection connection = DriverManager.getConnection(url, "root", "root");
3.创建statement对象,拼接sql语句
PreparedStatement ps = connection.prepareStatement("delete from t_stu where s_name = ?");
4.设置sql语句中的占位符的值
ps.setString(1,name);
5.执行sql语句并获取结果
ResultSet rs =ps.executeQuery();
6.对sql执行结果进行解析处理
while(rs.next()){
System.out.println("对执行sql的结果进行解析处理!")
}
7.关闭连接,释放资源。
通过我们对传统JDBC编程步骤的回顾,可以总结处以下四点问题:
1.数据库连接的频繁创建和释放造成了系统资源的浪费,进而影响系统性能。
2.SQL语句编写在Java代码中,这种硬编码造成代码不易维护,当SQL变动时需要修改Java源代码。
3.使用preparedStatement向占位符传参数存在硬编码,因为SQL语句的where条件中占位符的个数可能会改变。
4.对结果集解析存在硬编码,SQL语句改变会导致解析代码变化。
Mybatis的出现就可以很好的解决传统JDBC编程中出现的各种问题,这对于程序员专注业务和系统维护有着重大的意义。
MyBatis的架构从配置文件到底层java代码都是一环套一环的存在,下面的一幅图就是对此最完美的解析,一句话,读懂Mybatis架构图,会使你在学习Mybatis框架的过程中不迷茫。
首先,我们需要创建一个Maven项目,可以参照maven介绍+maven开发环境的搭建+常用maven命令这篇文章创建maven项目。我们需要在pom.xml文件中导入相关联的jar包,一个是Mybatis的相关jar包,这是实现Mybatis框架的根基,其次我们还需要导入我们所使用数据库的JDBC驱动包,我这里以MySql驱动包为例。
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
dependency>
MyBatis的配置文件包含了对Mybatis行为的设置信息,即上图中的SqlMapConfig.xml文件。配置文件的顶层结构如下(所有的标签必须要按照特定的顺序排放,如果没有可以不写,如果有必须按照响应顺序)
<configuration>
<properties resource="config.properties">properties>
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
<typeAliases>
<package name="com.cwd.mybatis.bean"/>
typeAliases>
<environments default="work">
<environment id="development">
<transactionManager type="JDBC">transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="" />
<property name="url" value="jdbc:hsqldb:mem:batch_keys" />
<property name="username" value="sa" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="mapper/UserMapper.xml" />
mappers>
configuration>
我们在sql的映射文件中配置操作数据库的sql语句,这里的sql映射文件对应Mybatis架构中的mapper.xml文件。sql映射文件需要在MyBatis全局配置文件中进行加载,在上面的9.mappers标签中引入映射文件地址。同时我们需要为映射文件创建对应的java接口,用来在java代码中调用对应的方法进行数据库操作。
我们以UserMapper.xml为例:
1.新建一个UserDao.java接口,可以让java代码通过此接口调用对应方法进行数据库操作。
package com.cwd.mybatis.dao;
import com.cwd.mybatis.bean.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface UserDao {
/*
接口中的方法名与映射文件中 id名相同
public void saveUser(User user);
}
2.新建UserMapper.xml映射文件
提示:需要往sql语句中传入参数时要区分#{}和${}
(1)#{}占位符,是经过预编译的,编译好SQL语句再取值,#方式能够防止sql注入;
(2) 拼 接 符 , 会 传 入 参 数 字 符 串 , 取 值 以 后 再 去 编 译 s q l 语 句 , {}拼接符,会传入参数字符串,取值以后再去编译sql语句, 拼接符,会传入参数字符串,取值以后再去编译sql语句,方式无法防止注入;
注意:排序时使用order by动态参数时要使用$而不是#
<mapper namespace="com.cwd.mybatis.dao.UserDao">
<insert id="saveUser" parameterType="com.cwd.mybatis.bean.User">
insert into t_user(name,age,birthday) values(#{name},#{age},#{birthday});
insert>
mapper>
注意:映射文件中的mapper标签的namespace属性值对应着UserDao接口的包路径,因为我们是通过SqlSession的mapper接口的方式执行sql语句,而且insert标签的id属性值要与接口中定义的方法名一致,否则会找不到映射的SQL标签。
3.在Mybatis全局配置文件中配置sql映射文件
<mappers>
<mapper resource="mapper/UserMapper.xml" />
mappers>
1.读取Mybatis全局配置文件
Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
2.创建SqlSessionFactory,用来封装mybatis的配置信息,创建SqlSession对象,由于创建SqlSessionFactory开销比较大,所以整个应用程序中只有一个实例
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
3.创建SqlSession,每次与数据库交互都需要创建一个轻量级的SqlSession对象,意味着创建数据库会话,与数据库会话完毕后关闭。
SqlSession sqlSession = sessionFactory.openSession();
4.获取要使用的接口对象,从而调用对应的方法
UserDao userDao = sqlSession.getMapper(UserDao.class);
userDao.saveUser(user);
5.提交事务
sqlSession.commit();
6.关闭SqlSession
sqlSession.close();