一、MyBatis 简单介绍及工作原理
什么是Mybatis?Mybatis有什么用?
(1) Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement、等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
(2) MyBatis可以使用XML或注解来配置和映射原生信息,将POJO映射成数据库中的记录,避免了几乎所有的JDBC 代码和手动设置参数以及获取结果集。
(3) 通过xml文件或注解的方式将要执行的各种statement 配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis 框架执行sql并将结果映射为java对象并返回。(从执行sql 到返回result 的过程)。
Mybaits的优点
(1) 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在XML 里,解除sql 与程序代码的耦合,便于统一管理;提供XML 标签,支持编写动态SQL语句,并可重用。
(2) 与JDBC相比,减少了50%以上的代码量,消除了JDBC 大量冗余的代码,不需要手动开关连接;
(3) 很好的与各种数据库兼容(因为MyBatis 使用JDBC 来连接数据库,所以只要JDBC 支持的数据库MyBatis 都支持)。
(4) 能够与Spring 很好的集成;
(5) 提供映射标签,支持对象与数据库的ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
MyBatis的执行原理详细介绍
为了使大家能够更加清晰的理解MyBatis程序,在正式讲解MyBatis入门案例之前,先来了解一下MyBatis程序的工作原理,如下图所示。
从中可以看出,MyBatis框架在操作数据库时,大体经过了8个步骤。下面就对图中的每一步流程进行详细讲解,具体如下。
(1) 读取MyBatis配置文件mybatis-config.xml。mybatis-config.xml作为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接。
(2) 加载映射文件Mapper.xml。Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
(3) 构建会话工厂。通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。
(4) 创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有方法。
(5) MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态的生成需要执行的SQL语句,同时负责查询缓存的维护。
(6) 在Executor接口的执行方法中,包含一个MappedStatement类型的参数,该参数是对映射信息的封装,用来存储要映射的SQL语句的id、参数等。Mapper.xml文件中一个SQL对应一个MappedStatement对象,SQL的id即是MappedStatement的id。
(7) 输入参数映射。在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型),Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对preparedStatement对象设置参数的过程。
(8) 输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO类型),Executor执行器会通过MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。
上面这部分转载于mybatis看这一篇就够了,简单全面快速入门_是一只萨摩耶的博客-CSDN博客
二、MyBatis 入门程序
创建一个Java项目后
⑴ 导入JAR包
1. ant-1.9.6.jar
2. ant-launcher-1.9.6.jar
3. asm-5.2.jar
4. cglib-3.2.5.jar
5. commons-logging-1.2.jar
6. javassist-3.22.0-GA.jar
7. log4j-1.2.17.jar
8. log4j-api-2.3.jar
9. log4j-core-2.3.jar
10. mybatis-3.4.6.jar 核心jar包
11. mysql-connector-java-5.1.46.jar MySQL驱动jar包
12. ognl-3.1.16.jar
13. slf4j-api-1.7.25.jar
14. slf4j-log4j12-1.7.25.jar
⑵ 配置文件
在项目的 src 目录下,创建 log4j.properties 文件,编辑后的内容如下:
# Global logging configuration
# 全局日志配置
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
# MyBatis 日志配置
log4j.logger.com.neko=TRACE
# Console output...
# 控制台日志输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
注意:在MyBatis 日志配置中 我的配置是 com.neko
⑶ 在 src 目录下,创建一个 com.neko.po 包,再创建 User 类
package com.neko.pojo;
public class User {
public User(Integer id, String username, String password, String code, String nikoname,String image){
super();
this.id = id;
this.username = username;
this.password = password;
this.code = code;
this.nikoname = nikoname;
this.image = image;
}
public User(){};
private Integer id;
private String username;
private String password;
private String code;
private String nikoname;
private String image;
public Integer getId() {
return id;
}
public void setId(Integer 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 getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getNikoname() {
return nikoname;
}
public void setNikoname(String nikoname) {
this.nikoname = nikoname;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", code=" + code + ", nikoname="
+ nikoname + ", image=" + image + "]";
}
}
⑷ 在 src 目录下,创建一个 com.neko.mapper 包,用来储存 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">
<!-- namespace表示命名空间 -->
<mapper namespace="com.neko.mapper.UserMapper">
<!-- 根据客户编号获取客户信息 -->
<select id="findUserById" parameterType="int" resultType="com.neko.po.User">
select * from tbl_user where id = #{id}
</select>
<!-- 增添数据 -->
<insert id="addUser" parameterType="com.neko.po.User">
insert into tbl_user(username,password,code,nikoname,image)
values(#{username},#{password},#{code},#{nikoname},#{image})
</insert>
<!-- 修改数据 -->
<update id="editUser" parameterType="com.neko.po.User">
update tbl_user set username=#{username},password=#{password}
where id=#{id}
</update>
<!-- 删除数据 -->
<delete id="delUser" parameterType="int">
delete from tbl_user where id=#{id}
</delete>
</mapper>
⑸ 在 src 目录下,创建 MyBatis 的核心配置文件 mybatis-config.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>
<!-- 1、配置环境,默认环境id为mysql -->
<environments default="mysql">
<!-- 1.1 配置环境id为mysql的数据库环境 -->
<environment id="mysql">
<!-- 使用JDBC事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/userdb?characterEncoding=utf8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root123"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/neko/mapper/UserMapper.xml"/>
</mappers>
</configuration>
⑹ 测试,在 src 目录下,创建一个 com.neko.test 包,在该包下创建测试类,
package com.neko.test;
import java.io.IOException;
import java.io.InputStream;
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.Test;
import com.neko.pojo.User;
public class MyBatisTest {
private static SqlSessionFactory sf = null;
static{
InputStream is;
try {
//定义输入流读取配置文件
is = Resources.getResourceAsStream("mybatis-config.xml");
//根据流对象构建工厂会话
sf = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
//从工厂会话中获取会话
SqlSession session =sf.openSession();
//使用会话的API执行sql
//selectOne("",3); "":根据..查询;3:查询第三条
User user = session.selectOne("com.neko.mapper.UserMapper.findUserById",2);
System.out.println(user);
// //测试添加
// User user = new User();
// user.setUsername("neko");
// user.setPassword("2333");
// user.setNikoname("会玩猫的iPhone");
// int result = session.insert("com.neko.mapper.UserMapper.addUser", user);
// if (result>0) {
// System.out.println("数据插入成功");
// }else {
// System.out.println("执行插入失败");
// }
// session.commit();
//关闭会话
session.close();
}
@Test
public void testAddUser(){
SqlSession session = sf.openSession();
User user = new User(0,"neko","123","ne","ne","null");
int result = session.insert("com.neko.mapper.UserMapper.addUser", user);
if (result>0) {
session.commit();
}else {
session.rollback();
}
System.out.println(result);
}
@Test
public void testDelUser(){
SqlSession session = sf.openSession();
int result = session.delete("com.neko.mapper.UserMapper.delUser",1 );
if (result>0) {
session.commit();
}else {
session.rollback();
}
System.out.println(result);
}
}
注意:在使用 MyBatis 框架时,主要涉及两个核心对象: SqlSessionFactory 和 SqlSession 。同时为了简化开发,我们把前者封装到一个工具类中,然后通过工具类来创建 SqlSession 。
创建SqlSession 的工具类:
package com.neko.util;
import java.io.IOException;
import java.io.InputStream;
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 {
private static SqlSessionFactory sf = null;
static {
InputStream is;
try {
//定义输入流--读取配置文件
is = Resources.getResourceAsStream("mybatis-config.xml");
//根据流对象构建工厂会话
sf = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* 获取SQLSession的静态方法
* @return SqlSession对象
*/
public static SqlSession getSqlSession() {
return sf.openSession();
}
}
二、MyBatis 的核心配置
1 创建SQLSession 的工具类,如上:
2 配置文件
2.1 使用自动扫描包自定义别名
<!-- 使用自动扫描包来定义别名 -->
<typeAliases>
<package name="com.neko.po"/>
</typeAliases>
注意:上述方式的别名只适用于没有使用注解的情况。
如果在程序中使用了注解,则别名为其注解的值,如下:
@Alias(value="customer")
public class Customer {
//Customer 的属性和方法
}
2.2 <environments>元素
mybatis-config 配置文件:
<?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="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/userdb?characterEncoding=utf8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root123"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/neko/mapper/UserMapper.xml"/>
</mappers>
</configuration>
2.3 <mappers>元素
在配置文件中,<mappers>元素用于指定 MyBatis 映射文件的位置,一般可以使用以下4种方法引入映射器文件,如下:
2.3.1 使用类路径引入(使用)
<mapper>
<mapper resource="com.neko.mapper.CustomerMapper.xml"/>
</mapper>
2.3.2 使用本地文件路径引入
<mapper>
<mapper url="file:///E: /src/com/neko/mapper/CustomerMapper.xml" />
</mapper>
2.3.3 使用接口类引入
<mapper>
<mapper class="com.neko.mapper.CustomerMapper" />
</mapper>
2.3.4 使用包名引入(使用)
<mapper>
<package name="com.neko.mapper"/>
</mapper>
根据实际项目需要选取使用即可。
下面是映射文件:
2.4 <select>元素
事例:
<select id="findCustomerById" parameterType="int" resultType="com.neko.po.Customer">
select * from tbl_customer where id = #{id}
</select>
id:表示命名空间的唯一标识符;
parameterType:表示传入 SQL 语句的参数类的全限定名或者别名;
resultType: 从 SQL 语句中返回的类型的类的全限定名或者别名;
resultMap:表示外部 resultMap 的引用。返回时可以使用 resultType 或 resultMap ;
flushCathe:表示在调用 SQL 语句后,是否需要 MyBatis 清空之前查询的本地缓存和二级缓存。其值为布尔类型,默认值为 false。如果设置为 true ,则任何时候只要 SQL 语句被调用,都会清空本地缓存和二级缓存;
-------------------------------------------------------------------------------------------------------------------------
useCathe:
timeOut:
fetchSize:
statementType:
resultSetType:
2.5 <insert>元素
2.6 <update>元素
2.7 <delete>元素
2.8 <sql>元素
2.9 <resultMap>元素
<resultMap> 元素表示结果映射集,是 MyBatis 中最重要也是最强大的元素。它的主要作用是定义映射规则、级联的更新以及定义类型转换器等。
<resultMap> 的元素结构如下:
<!-- resultMap 的元素结构 -->
<resultMap type="" id=""> <!-- type属性表示需要映射的POJO,id属性是这个resultMap 的唯一标识 -->
<constructor> <!-- 类在实例化时,用来注入结果到构造方法中 -->
<idArg /> <!-- ID参数;标记结果作为ID -->
<arg /> <!-- 注入到构造方法的一个普通结果 -->
</constructor>
<id /> <!-- 用于表示哪个列是主键 -->
<result /> <!-- 注入到字段或 JavaBean 属性的普通结果-->
<association property="" /> <!-- 用于一对一关联 -->
<collection property="" /> <!-- 用于一对多关联 -->
<dsicriminattor javaType=""> <!-- 使用结果值来决定使用哪个结果映射 -->
<case value="" /> <!-- 基于某些值的结果映射 -->
</dsicriminattor>
</resultMap>