1.概念
1.1.什么是Mybatis框架
(1)Mybatis是一个半ORM(Object Relation Mapping 对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
(2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)
1.2.Mybatis框架与JDBC区别
两者都是持久化的技术
连接数据库时 : mybatis 使用了 连接池技术 , 而jdbc需要自己写
持久化操作时 : mybatis 在映射文件中集中管理SQL语句 , 并且支持动态SQL
通常使用Mapper接口封装成面向对象的语法
而JDBC中的SQL是以参数的形式传入
结果集封装 : mybatis 封装了过程 , 只要指明对应结构就可以 , 而JDBC全手动
1.3.Mybatis框架与Hibernate框架区别
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
2.步骤
相较于JDBC来说, Mybatis完成持久化操作也分4个步骤, 需要七个参数
4个步骤 : 连接数据库, 持久化操作, 结果集封装, 释放资源
7个参数 : 驱动类路径, 连库信息, 用户名, 密码, SQL语句, SQL参数, 结果集封装结构
2.0.在idea中创建 Maven项目
2.1.依赖包
通过Maven 导入依赖, 同时导入 MySQL数据库的驱动依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
2.2.增加配置文件( 4/7参数 )
在 resources 文件夹中增加Mybatis的配置文件 mybatis-config.xml
在文件中 指明连接数据库的 4 个信息 驱动类路径
, url
, 用户名
, 密码
<?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"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/metamooc" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
2.3.连接数据库( 1/4 操作)
建立一个操作类, 增加连接数据库代码
// 读取myBatis的配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
// 创建SessionFactory工厂 与数据库建立 连接 conn
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
2.4.Mapper映射 ( 3/7 参数 , 1/4 操作)
2.4.1.实体类Entity
实体类Entity 用于封装数据, 通常与数据库的表对应 , 这里以 Teacher为例
import java.io.Serializable;
import java.util.Date;
/**
* 教师 teacher
* @TableName teacher
*/
public class Teacher implements Serializable {
/**
* 讲师主键
*/
private Integer tchId;
/**
* 讲师姓名
*/
private String tchName;
/**
* 讲师介绍
*/
private String tchInfo;
/**
* 讲师性别
*/
private Integer tchSex;
/**
* 讲师注册时间
*/
private Date tchRegTime;
/**
* 讲师头像
*/
private String tchPic;
/**
* 登录账号
*/
private String tchUser;
/**
* 登录密码
*/
private String tchPass;
@Override
public String toString() {
return "Teacher{" +
"tchId=" + tchId +
", tchName='" + tchName + '\'' +
", tchInfo='" + tchInfo + '\'' +
", tchSex=" + tchSex +
", tchRegTime=" + tchRegTime +
", tchPic='" + tchPic + '\'' +
", tchUser='" + tchUser + '\'' +
", tchPass='" + tchPass + '\'' +
'}';
}
public Integer getTchId() {
return tchId;
}
public void setTchId(Integer tchId) {
this.tchId = tchId;
}
public String getTchName() {
return tchName;
}
public void setTchName(String tchName) {
this.tchName = tchName;
}
public String getTchInfo() {
return tchInfo;
}
public void setTchInfo(String tchInfo) {
this.tchInfo = tchInfo;
}
public Integer getTchSex() {
return tchSex;
}
public void setTchSex(Integer tchSex) {
this.tchSex = tchSex;
}
public Date getTchRegTime() {
return tchRegTime;
}
public void setTchRegTime(Date tchRegTime) {
this.tchRegTime = tchRegTime;
}
public String getTchPic() {
return tchPic;
}
public void setTchPic(String tchPic) {
this.tchPic = tchPic;
}
public String getTchUser() {
return tchUser;
}
public void setTchUser(String tchUser) {
this.tchUser = tchUser;
}
public String getTchPass() {
return tchPass;
}
public void setTchPass(String tchPass) {
this.tchPass = tchPass;
}
}
2.4.2.Mapper接口
对 要执行的SQL 进行抽象声明
import com.yuan.mybatis.entity.Teacher;
import java.util.List;
/**
* @description 针对表【teacher(教师 teacher)】的数据库操作Mapper
* @Entity com.yuan.mybatis.entity.Teacher
*/
public interface TeacherMapper {
/**
* 全查
*/
List<Teacher> selectList();
/**
* 添加
*/
int insert(Teacher teacher);
/**
* 修改
*/
int updateById(Teacher teacher);
/**
* 根据id 删除记录
*/
int removeById(Integer id);
/**
* 根据id 查询一条记录
*/
Teacher selectOneById(Integer tchId);
/**
* 查询指定表的记录数
*/
int selectCount(String tabName);
/**
* 根据tch_user, tch_pass 查询一条记录
*/
Teacher selectOneByUserNameAndPassword(@Param("userName") String name, @Param("password") String pass);
}
2.4.3. ***映射文件
在 resources 文件夹下 mapper 文件夹中 增加 Mapper接口对应的映射文件 TeacherMapper.xml
其中(重点) :
2.4.3.1. namespace
根结点 mapper 的 namespace
属性 指向 Mapper 接口
<mapper namespace="com.yuan.mybatis.mapper.TeacherMapper">
2.4.3.2.resultMap
<resultMap>
结点 与 Entity 实体类 对应 , 通过 type
属性 对应类的路径
<id>
对应 主键 字段, <result>
为普通字段
property
对应 实体类的属性名 , column
对应 字段名 , jdbcType
对应类型(这个可以不写)
<resultMap id="BaseResultMap" type="com.yuan.mybatis.entity.Teacher">
<id property="tchId" column="tch_id" jdbcType="INTEGER"/>
<result property="tchName" column="tch_name" jdbcType="VARCHAR"/>
<result property="tchInfo" column="tch_info" jdbcType="VARCHAR"/>
<result property="tchSex" column="tch_sex" jdbcType="BOOLEAN"/>
<result property="tchRegTime" column="tch_reg_time" jdbcType="TIMESTAMP"/>
<result property="tchPic" column="tch_pic" jdbcType="VARCHAR"/>
<result property="tchUser" column="tch_user" jdbcType="VARCHAR"/>
<result property="tchPass" column="tch_pass" jdbcType="VARCHAR"/>
</resultMap>
2.4.3.3.SQL语句
<insert>
, <delete>
, <update>
, <select>
是用来编写 对应SQL 语句
id
与 Mapper接口 中声明的 方法名 对应
#{属性}
在SQL语句中作属性占位符, 执行时替换成对应值, 值是从Mapper接口传入的参数对应
如果传入是实体类, 属性取类的属性
<update id="updateById" parameterType="com.yuan.mybatis.entity.Teacher">
update teacher
set tch_name = #{tchName},
tch_info = #{tchInfo},
tch_sex = #{tchSex},
tch_reg_time = #{tchRegTime},
tch_pic = #{tchPic},
tch_user = #{tchUser},
tch_pass = #{tchPass}
where tch_id = #{tchId}
</update>
如果传入是单个值, 可以用类型如: list , array , id 等, 或者与参数名相同
<delete id="removeById" parameterType="java.lang.Integer">
delete from teacher
where tch_id = #{id}
</delete>
如果传入多个参数 , 对应的方法有多种, 推荐在传参时使用@Param("别名")
进行标注(这个可以不写)
<select id="selectOneByUserNameAndPassword" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from teacher
where tch_user = #{userName} and tch_pass = #{password}
limit 1
</select>
${值}
也是属性占位符, 直接替换为实际的参数值, 没有预编译效果,
只用于与参数无关的字符类型数据, 所以代表字符串时要用 单引号包围起来 '${}'
#{} 只能以预编译的形式为属性赋值 , 而 ${} 可以替代SQL语句中的表名, 字段名等结构信息
<select id="selectCount" resultType="java.lang.Integer" >
select count(*)
from ${tabName}
</select>
2.4.3.4.delete, update
<delete>
, <update>
这两个结点是用来编写 删除, 更新 对应SQL语句的
parameterType
属性 指明传入参数类型(这个可以不写)
<update id="updateById" parameterType="com.yuan.mybatis.entity.Teacher">
update teacher
set tch_name = #{tchName},
tch_info = #{tchInfo},
tch_sex = #{tchSex},
tch_reg_time = #{tchRegTime},
tch_pic = #{tchPic},
tch_user = #{tchUser},
tch_pass = #{tchPass}
where tch_id = #{tchId}
</update>
2.4.3.5.insert
<insert>
用于编写插入SQL语句
通常MySQL数据库主键设置成 自增长, 在添加之前不知道具体值, 通过下面的三个属性, 在添加完成后立刻可以通过实体类得到值
keyColumn
=“主键字段” keyProperty
=“对应实体类属性” useGeneratedKeys
=“使用生成的主键, 选 : true”
<insert id="insert" keyColumn="tch_id" keyProperty="tchId"
parameterType="com.yuan.mybatis.entity.Teacher" useGeneratedKeys="true">
insert into teacher (tch_name, tch_info, tch_sex,tch_reg_time, tch_pic, tch_user,tch_pass)
values (#{tchName}, #{tchInfo}, #{tchSex},#{tchRegTime}, #{tchPic}, #{tchUser}, #{tchPass})
</insert>
2.4.3.6.SQL片段
<sql>
编写 可复用的SQL语句片段,
在其它语句中 通过 <include>
进行引入 refid
与 id
属性对应
<sql id="Base_Column_List">
tch_id,tch_name,tch_info,
tch_sex,tch_reg_time,tch_pic,
tch_user,tch_pass
</sql>
<select id="selectList" resultMap="BaseResultMap" >
select <include refid="Base_Column_List"/>
from teacher
</select>
2.4.3.7.select
<select>
用于编写查询SQL语句 , 通过 指定返回值类型完成结果集封装
resultMap
属性 是用于指明返回的实体类 , 与 <resultMap>
结点的 id 属性对应
<select id="selectOneById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from teacher
where tch_id = #{tchId}
</select>
resultType
属性 也是用于指明返回值类型, 用于指明除 实体类以外的通用类型
<select id="selectCount" resultType="java.lang.Integer" >
select count(*)
from ${tabName}
</select>
2.4.3.8.完整文件
<?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.yuan.mybatis.mapper.TeacherMapper">
<resultMap id="BaseResultMap" type="com.yuan.mybatis.entity.Teacher">
<id property="tchId" column="tch_id" jdbcType="INTEGER"/>
<result property="tchName" column="tch_name" jdbcType="VARCHAR"/>
<result property="tchInfo" column="tch_info" jdbcType="VARCHAR"/>
<result property="tchSex" column="tch_sex" jdbcType="BOOLEAN"/>
<result property="tchRegTime" column="tch_reg_time" jdbcType="TIMESTAMP"/>
<result property="tchPic" column="tch_pic" jdbcType="VARCHAR"/>
<result property="tchUser" column="tch_user" jdbcType="VARCHAR"/>
<result property="tchPass" column="tch_pass" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
tch_id,tch_name,tch_info,
tch_sex,tch_reg_time,tch_pic,
tch_user,tch_pass
</sql>
<select id="selectList" resultMap="BaseResultMap" >
select <include refid="Base_Column_List"/>
from teacher
</select>
<select id="selectOneById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from teacher
where tch_id = #{tchId}
</select>
<select id="selectCount" resultType="java.lang.Integer" >
select count(*)
from ${tabName}
</select>
<delete id="removeById" parameterType="java.lang.Integer">
delete from teacher
where tch_id = #{id}
</delete>
<insert id="insert" keyColumn="tch_id" keyProperty="tchId"
parameterType="com.yuan.mybatis.entity.Teacher" useGeneratedKeys="true">
insert into teacher (tch_name, tch_info, tch_sex,tch_reg_time, tch_pic, tch_user,tch_pass)
values (#{tchName}, #{tchInfo}, #{tchSex},#{tchRegTime}, #{tchPic}, #{tchUser}, #{tchPass})
</insert>
<update id="updateById" parameterType="com.yuan.mybatis.entity.Teacher">
update teacher
set tch_name = #{tchName},
tch_info = #{tchInfo},
tch_sex = #{tchSex},
tch_reg_time = #{tchRegTime},
tch_pic = #{tchPic},
tch_user = #{tchUser},
tch_pass = #{tchPass}
where tch_id = #{tchId}
</update>
</mapper>
2.4.4.在配置文件中声明
在 Mybatis的主配置文件中, 增加映射文件的声明
<?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"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/metamooc" />
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射声明 -->
<mappers>
<mapper resource="mapper/TeacherMapper.xml"></mapper>
</mappers>
</configuration>
2.5.持久化操作( 1/4 操作)
持久化操作先要得到 SqlSession实例,
再得到Mapper接口的实例,
// 取出一个session 得到对数据持久化操作的句柄 stmt
SqlSession session = sqlSessionFactory.openSession();
// 通过session得到Mapper, 再通过 Mapper对象调用方法完成持久化操作
TeacherMapper teacherMapper = session.getMapper(TeacherMapper.class);
通过实例调用方法完成持久化操作 如:
// 插入数据
int insert = teacherMapper.insert(teacher);
// 查询数据
List<Teacher> list = teacherMapper.selectList();
2.5.1.事务提交
进行 插入数据, 修改数据, 删除数据时 要手动处理事务
如果操作没有问题 提交事务, 出现问题 事务回滚
// 提交
session.commit();
// 或者 回滚
session.rollback();
2.6.释放资源(1/4 操作)
由于 连接数据库时 使用连接池, 所以只需要释放session实例
// 关闭 session
session.close();