什么是 MyBatis
一款优秀的持久层框架。MyBatis 使用 XML 将 SQL 与程序解耦,便于维护。MyBatis 学习成本低,执行高效,底层是对 JDBC 的封装和扩展。
- MyBtis官网:
https://mybatis.org/mybatis-3/zh/index.html
- github地址:
https://github.com/mybatis/mybatis-3/releases
创建一个 MyBatis 项目的整体流程
- 创建数据库
- 创建数据表(本文的表结构和数据都不复杂)
- 创建基于 Maven 的 java 项目(上一节内容手把手实践过的)
- 项目基本配置完成,保证项目与数据库可以连接成功
- 通过项目中 Java 代码操作数据库中数据表的数据
- 业务功能完成,项目上线(发布项目)
以上 6 点,其中前 3 点之前的内容都有实战,这里不再做详细介绍,4 和 5 是本节的核心内容,最后一点不在本节内容实战,等学完 SSM 综合框架后,会专门做讲解,那个时候也更适合一些。
保证项目与数据库链接成功
1、创建数据表 tv_series
一条记录是一部电视剧的简单记录,包括这些信息:
tv_id
:主键自增,不可为空。
tv_title
:电视剧名称,也就是标题,不可为空。
tv_sub_title
:电视剧描述,也可以是子标题宣传短文本。
tv_type
:电视剧的类型,这里列举了 悬疑
、武侠
、江湖
、爱情
、宫廷
、乡村
6 类。
2、创建基于 Maven 的 Java 项目
创建步骤这里不做解释,需要提示一点,当创建项目点击了最后的 Nnext
按钮后,在新的 IDE 窗口中右下角会出现如下图提示,记得点击这里箭头标注的地方:
如果你能看到红框标注的信息,这就说明项目是构建成功的。可以接下来的工作啦!
3、完成项目基本配置
下图是在创建完成后的项目结构基础上,增加了必须的配置,大家可以跟自己创建的新项目对比一下,箭头标注的都是需要手动创建的:
这里做具体的解释,操作步骤基本都是“套路”,哈哈
- 红色剪头1,需要做的工作
创建目录,关于这个目录的名字还有讲究,一般大家都习惯叫 domain
、bean
、entity
,选择一个即可。该目录下的所有 calss
都和数据库中的表字段相对应,数据数据表中字段是用下划线分割的,那么这个类里面的变量就用驼峰来命名,小编这里的示例代码如下:
package com.javafirst.bean;
/**
* desc: 数据表对应的 java 实体类
* author weChat: studyingJava
*/
public class TVSeriesBean {
private int tvId;
private String tvTitle;
private String tvSubTitle;
private int tvType;
public int getTvId() {
return tvId;
}
public void setTvId(int tvId) {
this.tvId = tvId;
}
public String getTvTitle() {
return tvTitle;
}
public void setTvTitle(String tvTitle) {
this.tvTitle = tvTitle;
}
public String getTvSubTitle() {
return tvSubTitle;
}
public void setTvSubTitle(String tvSubTitle) {
this.tvSubTitle = tvSubTitle;
}
public int getTvType() {
return tvType;
}
public void setTvType(int tvType) {
this.tvType = tvType;
}
@Override
public String toString() {
return "TVSeriesBean打印信息:n{"
"tvId=" tvId
", tvTitle='" tvTitle '''
", tvSubTitle='" tvSubTitle '''
", tvType=" tvType
'}';
}
}
这里手动生成了 setXXX()
、getXXX()
方法,其实还有一些插件可以自动搞定,这里先不做用法,不适合新手。
- 红色剪头2,需要做的工作
手动创建文件夹,关于命名一般叫做 dao
,你也可以定义为你喜欢的哈。该包下的所有文件都是 interface
类型,专门用于提供接口,接口对应操作的是 sql
语句,而 sql
语句影响的是数据库中的数据,这就把项目和数据库建立了联系,但到这一步,还远远不能访问通。
该类的示例代码如下,其他可根据业务进行扩展:
代码语言:java复制package com.javafirst.dao;
import com.javafirst.bean.TVSeriesBean;
import java.util.List;
/**
* desc: 与数据库操作的相关业务接口
* <p>
* author weChat: studyingJava
*/
public interface TVSeriesDao {
/**
* 根据 id 查询某部电视剧
*
* @param tvId
* @return
*/
TVSeriesBean selectTVSeriesById(Integer tvId);
/**
* 查询所有电视剧
*
* @return
*/
List<TVSeriesBean> selectTVSeriesAll();
/**
* 添加一条记录(电视剧)通过字段方式
*
* @param title
* @param subTitle
* @param type
*/
void addTVSeriesOne(String title, String subTitle, int type);
/**
* 添加一条记录(电视剧)通过对象方式
*
* @param tvSeriesBean
*/
void addTVSeriesObject(TVSeriesBean tvSeriesBean);
}
- 红色剪头3,需要做的工作
在 main
目录下新建与 java
平级的文件夹 resources
,新建的时候 IDEA 会自动识别,不需要我们手动收入该名称,直接选中回车即可创建成功。
- 红色剪头4,需要做的工作
在第 3 步的基础上,接着在 resources
目录下创建 mapper
文件夹,然后创建 XXXMapper.xml
,这个文件和前面创建的 xxxDao
文件是对应的,所以尽量起名保持一致,项目复杂的时候能一眼识别,便于维护和理解。小编这里创建的是 TVSeriesMapper.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="com.javafirst.dao.TVSeriesDao">
</mapper>
这里其他的都是固定写法,唯一需要改变的是 mapper
标签里的 namespace
的值,很熟悉吧,这个值就是我们前面已经创建过的 XXXdao
的全路径。
mapper
标签里面的节点,就是我们日常操作表的 xml 语法,包括 <select>
、<insert>
、<update>
、<delete>
这些标签,而这些标签里面的内容就是我们在《推荐学java——数据表操作》章节学习过的 sql
语句。具体本文后面会给出示例代码。
- 红色剪头5,需要做的工作
在第三步的基础上,接着在 resources
目录下创建 mybatis-config.xml
,此文件的命名不是固定的,但一般都写这个名字,因为它的作用就是通过配置保证 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"/>
<dataSource type="POOLED">
<!-- mysql驱动-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- 指定数据库开放的端口、要连接的数据库名、编码方式-->
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=utf8"/>
<!-- mysql用户名-->
<property name="username" value="root"/>
<!-- mysql登录密码-->
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 这里配置每个mapper文件 -->
<mapper resource="mapper/TVSeriesMapper.xml"/>
</mappers>
</configuration>
同样这里的代码基本都是模板,只需要修改几个关键地方就可以了。
代码语言:html复制 <!-- 指定数据库开放的端口、要连接的数据库名、编码方式-->
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=utf8"/>
<!-- mysql用户名-->
<property name="username" value="root"/>
<!-- mysql登录密码-->
<property name="password" value="root"/>
- 这里小编是在本地跑项目,所以
url
的值localhost:3306
是本地的,如果你在安装mySQL
的时候修改了端口号,那么这里要使用你修改过的; mybatis_demo
是我们前面创建的数据库的名字,也就是本节内容整体流程里的第一步;username
值对应的是你登录mysql的账户名,这在我们《推荐学java——初识数据库》一节里讲解过了;password
值对应的是你登录mysql的密码;
- 红色剪头6,需要做的工作
pom.xml
文件在项目创建成功后会自动生成,我们需要做的就是在里面配置依赖项,这就要用到我们上一节学习到的内容了《推荐学java——Maven初识》 ,小编这里做了 mySql驱动
和 mybatis依赖
配置后的完整代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javafirst</groupId>
<artifactId>TV_series</artifactId>
<version>1.0</version>
<!-- 暂时注释掉 -->
<!-- <name>TV_series</name>-->
<!-- <!– FIXME change it to the project's website –>-->
<!-- <url>http://www.example.com</url>-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- 单元测试(默认添加) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- mySql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
比如后期要用到什么三方的框架之类的,都可以在上节内容提到的 maven仓库
搜索配置,然后添加到这里,这就是 maven 的方便之处。
- 红色剪头7,需要做的工作
到这一步基本的配置工作已经完成了,剩下的就是业务代码和逻辑了,前面这 6 步操作基本上每次我们创建项目都会做这些工作,大家需要熟练掌握流程。
这里有个小技巧:
XXXmapper.xml
和mybatis-config.xml
其实可以利用IDEA
的模板功能,方便快捷。
这里我们新建通用的包 utils
,暂时我们只会新建 MyBatisUtil.java
,示例代码如下:
package com.javafirst.utils;
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 java.io.IOException;
import java.io.InputStream;
/**
* desc:MyBatis工具类
* <p>
* author weChat: studyingJava
*/
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory = null;
static {
String configXml = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(configXml);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession openSqlSession() {
SqlSession sqlSession = null;
if (null != sqlSessionFactory) {
sqlSession = sqlSessionFactory.openSession();
} else {
String configXml = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(configXml);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
}
}
return sqlSession;
}
}
之所以会有这个工具类,是因为我们要避免重复的代码,关于为什么这样写,大家可以在 MyBatis
官网查看。
下面就开始写功能代码,测试链接数据,激动人心的时刻要到来了!
4、测试链接成功
本文的核心是 MyBatis
,现在我们就测试下 MyBatis
与数据库链接是否成功,代码如下:
@Test
public void testSqlConnection() {
SqlSession sqlSession = MyBatisUtil.openSqlSession();
System.out.println("测试 MyBatis 链接数据库驱动:" sqlSession.toString());
}
这段代码大家自行新建一个java类,然后写上这段代码,进行单元测试,结果如下图,则为链接成功,说明前面的 mybatis-config.xml
里的配置没有出错。
操作数据表
接下来就可以操作数据库中的表了,在本文的最开始我们新建了一张表,里面没有任何数据,现在我们先来做一次查询,然后再做一次插入数据,再做一次全部查询,证明我们通过java项目可以操作数据库。
- 查询所有记录
单元测试 java 方法如下:
代码语言:java复制 /**
* 查询所有记录
*/
@Test
public void testSelectTVSeriesAll() {
SqlSession sqlSession = MyBatisUtil.openSqlSession();
TVSeriesDao tvSeriesDao = sqlSession.getMapper(TVSeriesDao.class);
List<TVSeriesBean> tvSeriesBeans = tvSeriesDao.selectTVSeriesAll();
sqlSession.close();
System.out.println("查询所有记录(电视剧):" tvSeriesBeans.size());
for (TVSeriesBean tvSeries : tvSeriesBeans) {
System.out.println(tvSeries);
}
}
对应的 mapper.xml
中的 select
语句如下:
<mapper namespace="com.javafirst.dao.TVSeriesDao">
<!-- 查询所有记录 -->
<select id="selectTVSeriesAll" resultType="com.javafirst.bean.TVSeriesBean">
select * from tv_series
</select>
</mapper>
需要注意,这里的 id
,需要和我们 xxxDao
中定义的接口名保持一致。
sql 语句和我们以往不同的是,这里不再需要以 `;` 结尾了。执行后的结果如下则为正确。
- 添加一条记录
添加记录我们使用两种方式,一种是通过字段传值的方式;一种是通过创建对象的方式;这两种方式都需要注意表中的 tv_id
是主键,自增的,所以我们不需要给这个字段设置值。
第一种方式:
代码语言:java复制 /**
* 添加一条记录 通过字段方式
*/
@Test
public void testAddTVSeriesOne() {
SqlSession sqlSession = MyBatisUtil.openSqlSession();
TVSeriesDao tvSeriesDao = sqlSession.getMapper(TVSeriesDao.class);
tvSeriesDao.addTVSeriesOne("《射雕英雄传》", "金庸武侠经典之作,永久传承", 1);
sqlSession.commit();
sqlSession.close();
System.out.println("添加记录成功!");
}
添加记录的时候相比于查询需要多一步操作,就是 sqlSession.commit()
,这个要和我们之前学过的事务有关,MySQL 是默认开启事务的,所以插入记录后,我们需要手动提交事务才起作用。当然我们也可以在 MyBatisUtil.java
工具类中在初始化 SqlSession
的时候通过参数来指定默认自动提交,即:
sqlSession = sqlSessionFactory.openSession(true);
对应的 mapper
文件中的 insert
标签内容如下:
<insert id="addTVSeriesOne">
insert into tv_series (tv_title,tv_sub_title,tv_type) values (#{param1},#{param2},#{param3})
</insert>
如果使用字段方式,这里的列值(也叫参数)推荐使用
#{param 数字}
这种方式,否则可能会遇到坑。
执行结果如下,则正确插入一条记录,此时,可以打开 Navicat
查看表中数据(这里不展示截图了)。
第二种方式:
java代码如下
代码语言:java复制/**
* 添加一条记录 通过对象方式
*/
@Test
public void testAddTVSeriesObject() {
SqlSession sqlSession = MyBatisUtil.openSqlSession();
TVSeriesDao tvSeriesDao = sqlSession.getMapper(TVSeriesDao.class);
TVSeriesBean tvSeriesBean = new TVSeriesBean();
tvSeriesBean.setTvTitle("《天龙八部》");
tvSeriesBean.setTvSubTitle("北宋末年,宋辽边境冲突不断,一场大阴谋正在悄然来袭...");
tvSeriesBean.setTvType(2);
tvSeriesDao.addTVSeriesObject(tvSeriesBean);
sqlSession.commit();
sqlSession.close();
System.out.println("添加记录成功!!");
}
对应的 mapper
文件中的 insert
标签内容如下:
<insert id="addTVSeriesObject">
insert into tv_series (tv_title,tv_sub_title,tv_type) values (#{tvTitle},#{tvSubTitle},#{tvType})
</insert>
这里需要注意传参(列值),这种方式需要和自定义的实体类中的字段值保持一致,否则会出现映射异常。
到这一步,我们已经添加了两条记录了,用我们前面的查询所有记录测试方法,看看是否真的有两条数据,看下图:
注意到没? 奇怪的问题发生了,数据总数是合适的,但是每条记录都显示为 null
,这明显是不对的,因为我们已经重写了 toString()
方法啊。
细心的同学有没注意到我们在前面第一步写实体类的时候,提到使用驼峰命名才能和数据表中带有下划线的字段对应(映射)起来,但我们没有在 mybatis-config.xml
中配置打开驼峰匹配开关,现在添加如下代码:
<!-- 开启驼峰命名映射 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
再次执行查询结果如下:
这是初学者需要注意的一个点,切记!
- 删除一条记录
我们需要先在 TVSeriesDao
中增加一个接口 void deleteTVSeriesBeanById(Integer tvId);
,然后在测试类中增加如下方法:
/**
* 删除一条记录 根据ID
*/
@Test
public void testDeleteTVSeriesBeanById() {
SqlSession sqlSession = MyBatisUtil.openSqlSession();
TVSeriesDao tvSeriesDao = sqlSession.getMapper(TVSeriesDao.class);
tvSeriesDao.deleteTVSeriesBeanById(2);
sqlSession.commit();
sqlSession.close();
System.out.println("删除一条记录成功!!");
}
到这还没有完,还需要在 TVSeriesMapper.xml
中增加如下代码:
<!-- 删除记录 根据ID -->
<delete id="deleteTVSeriesBeanById">
delete from tv_series where tv_id = #{tvId}
</delete>
代码语言:txt复制到这就可以运行测试方法了,结果如下:
代码语言:txt复制![根据ID删除一条记录](https://gitee.com/codexiaosheng/md-pictures/raw/master/2021-12-16/1639648382954-image.png)
代码语言:txt复制可以通过再次查询或者直接查看数据库中表的数据证明结果的正确性,这里就不贴图了。
细心的同学有没有发现,当我们前期的工作搞定之后,剩下的基本都是固定的操作模式,需要修改的地方都很流程化。
- 修改记录
为了演示这个功能,我们就把现在剩余的一条记录的 title
修改为 《新版射雕英雄传》
,下面是完整示例代码:
接口代码
代码语言:java复制 /**
* 根据ID 来修改标题
* @param tvId
*/
void updateTVSeriesBeanTitleById(Integer tvId,String tvTitle);
TVSeriesMapper.xml
中代码:
<!-- 更新记录 根据ID -->
<update id="updateTVSeriesBeanTitleById">
update tv_series set tv_title = #{param2} where tv_id = #{param1}
</update>
测试方法代码:
代码语言:java复制 /**
* 修改指定记录的数据
*/
@Test
public void testUpdateTVSeriesBeanTitleById() {
SqlSession sqlSession = MyBatisUtil.openSqlSession();
TVSeriesDao tvSeriesDao = sqlSession.getMapper(TVSeriesDao.class);
tvSeriesDao.updateTVSeriesBeanTitleById(1, "《新版射雕英雄传》");
sqlSession.commit();
sqlSession.close();
System.out.println("update一条记录成功!!");
}
执行结果如下:
此时打开数据库,或者再次执行查询查看结果,就是我们修改过的结果。
到这里,我们的基本增删改查都已经实操了一遍,这是核心内容,关于前期项目配置那一套,自己实操一遍,把流程记录下来,这就是本节的核心内容。
但本节的操作都是基于单表,操作业务特别单一简单,比如我们插入一条数据现在是没有任何途径证明是插入成功的,那么能不能插入后给我返回该条记录的主键呢?删除也是相同的道理,因为真实业务中我们不可能每次都查看数据库,而且大项目中,表中的记录可能千万条,查看也不现实,所以关于 MyBatis 的高级内容后面章节就会讲解到,大家赶紧撸码吧~~
总结
- MyBatis 是一个框架,掌握其使用流程和高级用法是一个合格Java工程师必备条件
- 前期学习的 SQL 知识要熟练掌握,本节的内容亦是如此,知识环环相扣
- 学习编程没有捷径,埋头苦练即可