几个简单实例
在这一节中,我们将通过几个实例来学习 MyBatis 的用法,提供的例子中不仅仅只有 MyBatis 部分的代码,还包含 Service、Controller、JSP 的代码。这一节会通过一整套的代码来演示 MyBatis 在项目开发中的基本用法。按照自下而上的顺序进行开发,从 Mapper 开始,依次开发 Service 层、Controller 层、JSP 前端页面。在实际开发过程中,可能会根据每一层的需求对各层接口进行调整。
基本准备
在开始之前需要先准备数据库、表和数据,9.2节配置的数据源连接的仍是本地的 mybatis 数据库,这一节会新增一个字典表,然后针对这个字典表进行增、删、改、查 4 类操作。字典表的建表语句和基础数据的 SQL 如下。
DROP TABLE IF EXISTS sys_dict;
CREATE TABLE sys_dict(
id BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT 'ID',
code VARCHAR(64) NOT NULL COMMENT '类别',
name VARCHAR(64) NOT NULL COMMENT '字典名',
value VARCHAR(64) NOT NULL COMMENT '字典值',
PRIMARY KEY (id)
)ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
INSERT INTO sys_dict VALUES (1,'性别','男','男');
INSERT INTO sys_dict VALUES (2,'性别','女','女');
INSERT INTO sys_dict VALUES (3,'季度','第一季度','1');
INSERT INTO sys_dict VALUES (4,'季度','第二季度','2');
INSERT INTO sys_dict VALUES (5,'季度','第三季度','3');
INSERT INTO sys_dict VALUES (6,'季度','第四季度','4');
在 src/main/java 中新建 tk.mybatis.web.model 包,然后新建 SysDict 实体类。
public class SysDict implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String code;
private String name;
private String value;
//setter和getter方法
}
开发Mapper层(Dao层)
Mapper 层也就是常说的数据访问层(Dao 层)。使用 Mapper 接口和 XML 映射文件结合的方式进行开发,在9.3节集成 MyBatis 的配置中,自动扫描接口的包名为 tk.mybatis.**.mapper,因此在创建 Mapper 接口所在的包时也要参照这个命名规则。在 src/main/java 中新建 tk.mybatis.web.mapper 包,然后新建 DictMapper 接口。
public interface DictMapper {
}
同时,9.3 节的 SqlSessionFactoryBean 中也配置了扫描 XML 映射文件的目录 classpath:tk/mybatis/*/mapper/.xml。
在 src/main/resources 中新建 tk/mybatis/web/mapper/ 目录,然后新建 DictMapper.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.zccoder.mybatis2.ch9.spring.mapper.DictMapper">
</mapper>
经过前面几章的学习,此处直接将接口和对应的 XML 代码同时列出,不再对代码内容做详细的说明。
首先,当需要查看或修改某个具体的字典信息时,要有一个通过主键获取字典信息的方法,在 Mapper 接口和对应的 XML 中分别添加如下代码。
/**
* 根据主键查询
*
* @param id ID
* @return 字典
*/
SysDict selectByPrimaryKey(Long id);
<select id="selectByPrimaryKey" resultType="com.zccoder.mybatis2.ch9.spring.model.SysDict">
select id, code, name, `value` from sys_dict where id = #{id}
</select>
因为9.3节配置 SqlSessionFactoryBean 时,将 typeAliasesPackage 配置为 com.isea533.mybatis.model,所以这里设置 resultType 时可以直接使用类名,省略包名。
以下代码依次是根据字典参数和分页参数查询字典信息的方法,新增、更新、删除字典的接口的方法。
/**
* 条件查询
*
* @param sysDict 字典
* @param rowBounds 分页
* @return 字典列表
*/
List<SysDict> selectBySysDict(SysDict sysDict, RowBounds rowBounds);
/**
* 新增
*
* @param sysDict 字典
* @return 影响条数
*/
int insert(SysDict sysDict);
/**
* 根据主键更新
*
* @param sysDict 字典
* @return 影响条数
*/
int updateById(SysDict sysDict);
/**
* 根据主键删除
*
* @param id ID
* @return 影响条数
*/
int deleteById(Long id);
这 4 个接口方法对应的 XML 代码如下。
<select id="selectBySysDict" resultType="com.zccoder.mybatis2.ch9.spring.model.SysDict">
select * from sys_dict
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="code != null and code != ''">
and code = #{code}
</if>
</where>
order by code, `value`
</select>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into sys_dict(code, name, value)
values (#{code}, #{name}, #{value})
</insert>
<update id="updateById">
update sys_dict
set code = #{code},
name = #{name},
value = #{value}
where id = #{id}
</update>
<delete id="deleteById">
delete from sys_dict where id = #{id}
</delete>
这 5 个方法都是很基础的方法,通过这 5 个方法就可以实现字典表的基本操作。下面将在这 5 个接口的基础上,继续编写 Service 层的代码。
开发业务层(Service层)
虽然针对接口编程对小的项目来说并不重要,但是这里为了形式上的需要仍然提供了 Service 接口。在 src/main/java 中新建 tk.mybatis.web.service 包,然后添加 DictService 接口,代码如下。
public interface DictService {
/**
* 通过ID查询字典
*
* @param id ID
* @return 字典
*/
SysDict findById(Long id);
/**
* 分页查询
*
* @param sysDict 字典
* @param offset 开始位置
* @param limit 长度
* @return 字典列表
*/
List<SysDict> findBySysDict(SysDict sysDict, Integer offset, Integer limit);
/**
* 保存或更新
*
* @param sysDict
* @return 结果
*/
boolean saveOrUpdate(SysDict sysDict);
/**
* 删除
*
* @param id ID
* @return 结果
*/
boolean deleteById(Long id);
}
Service 层的 saveOrUpdate 方法对应 Mapper 中的 insert 和 updateById 方法,其他 3 个方法和 Mapper 层方法一一对应。在 tk.mybatis.web.service 包下创建 impl 包,然后新建 DictService 接口的实现类 DictServiceImpl,代码如下。
@Service
public class DictServiceImpl implements DictService {
@Autowired
private DictMapper dictMapper;
@Override
public SysDict findById(Long id) {
return dictMapper.selectByPrimaryKey(id);
}
@Override
public List<SysDict> findBySysDict(SysDict sysDict, Integer offset, Integer limit) {
RowBounds rowBounds = RowBounds.DEFAULT;
if (offset != null && limit != null) {
rowBounds = new RowBounds(offset, limit);
}
return dictMapper.selectBySysDict(sysDict, rowBounds);
}
@Override
public boolean saveOrUpdate(SysDict sysDict) {
if (sysDict.getId() == null) {
return dictMapper.insert(sysDict) == 1;
} else {
return dictMapper.updateById(sysDict) == 1;
}
}
@Override
public boolean deleteById(Long id) {
if (id == null) {
throw new NullPointerException("id");
}
return dictMapper.deleteById(id) == 1;
}
}
Service 的实现类中需要添加 @Service 注解,在9.2节集成 Spring 时配置过自动扫描包,包名是 tk.mybatis.web.service.impl,DictServiceImpl 实现类所在的包就是符合这个包名规则的,加上注解后,Spring 在初始化时就会扫描到这个类,然后由 Spring 管理这个类。因为配置了自动扫描 Mapper 接口,所以在 Service 层可以直接通过以下代码注入 Mapper。
@Autowired
private DictMapper dictMapper;
通过自动扫描 Mapper 和自动注入可以更方便地使用 MyBatis。
开发控制层(Controller层)
在 tk.mybatis.web.controller 包下,新建 DictController 类,代码如下。
@Controller
@RequestMapping("/dicts")
public class DictController {
@Autowired
private DictService dictService;
/**
* 显示字典数据列表
*
* @param sysDict 字典
* @param offset 开始位置
* @param limit 长度
* @return 字典列表
*/
@RequestMapping
public ModelAndView dicts(SysDict sysDict, Integer offset, Integer limit) {
ModelAndView mv = new ModelAndView("dicts");
List<SysDict> dicts = dictService.findBySysDict(sysDict, offset, limit);
mv.addObject("dicts", dicts);
return mv;
}
/**
* 新增或修改字典信息页面,使用 get 跳转到页面
*
* @param id ID
* @return 列表页
*/
@RequestMapping(value = "add", method = RequestMethod.GET)
public ModelAndView add(Long id) {
ModelAndView mv = new ModelAndView("dict_add");
SysDict sysDict;
if (id == null) {
//如果 id 不存在,就是新增数据,创建一个空对象即可
sysDict = new SysDict();
} else {
//如果 id 存在,就是修改数据,把原有的数据查询出来
sysDict = dictService.findById(id);
}
mv.addObject("model", sysDict);
return mv;
}
/**
* 新增或修改字典信息,通过表单 post 提交数据
*
* @param sysDict 字典
* @return 编辑页
*/
@RequestMapping(value = "add", method = RequestMethod.POST)
public ModelAndView save(SysDict sysDict) {
ModelAndView mv = new ModelAndView();
try {
dictService.saveOrUpdate(sysDict);
mv.setViewName("redirect:/dicts");
} catch (Exception e) {
mv.setViewName("dict_add");
mv.addObject("msg", e.getMessage());
mv.addObject("model", sysDict);
}
return mv;
}
/**
* 通过 id 删除字典信息
*
* @param id ID
* @return 结果
*/
@RequestMapping(value = "delete", method = RequestMethod.POST)
@ResponseBody
public ModelMap delete(@RequestParam Long id) {
ModelMap modelMap = new ModelMap();
try {
boolean success = dictService.deleteById(id);
modelMap.put("success", success);
} catch (Exception e) {
modelMap.put("success", false);
modelMap.put("msg", e.getMessage());
}
return modelMap;
}
}
上面这段代码中使用了两个视图,分别为 dicts 和 dict_add。在下一节中,我们将继续编写视图层代码。
开发视图层(View层)
按照9.2节中的视图配置,需要在 src/main/webapp 下面的 WEB-INF 中创建 jsp 目录,然后在 jsp 中创建 dicts.jsp 和 dict_add.jsp,dicts.jsp 代码如下。
<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<c:set var="path" value="${pageContext.request.contextPath}"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8">
<title>字典信息</title>
<script src="${path}/static/jquery-3.1.1.min.js"></script>
</head>
<body>
<table>
<tr>
<th colspan="4">字典管理</th>
</tr>
<tr>
<th>类别名</th>
<th>字典名</th>
<th>字典值</th>
<th> 操作 [<a href="${path}/dicts/add">新增</a>]</th>
</tr>
<c:forEach items="${dicts}" var="dict">
<tr id="dict-${dict.id}">
<td>${dict.code}</td>
<td>${dict.name}</td>
<td>${dict.value}</td>
<td>
[<a href="${path}/dicts/add?id=${dict.id}">编辑</a>]
[<a href="javascript:;" onclick="deleteById(${dict.id}, '${dict.name}')">删除</a>]
</td>
</tr>
</c:forEach>
</table>
<script>
function deleteById(id, label){
var r = confirm('您确定要删除“' + label + '”吗?');
if(r){
$.ajax({
url: '${path}/dicts/delete',
data: {
id: id
},
dataType: 'json',
type: 'POST',
success: function(data){
if(data.success){
$('#dict-' + id).remove();
} else {
alert(data.msg);
}
}
})
}
}
</script>
</body>
</html>
dict_add.jsp 代码如下。
<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<c:set var="path" value="${pageContext.request.contextPath}"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8">
<title>字典维护</title>
</head>
<body>
<form action="${path}/dicts/add" method="post">
<input type="hidden" name="id" value="${model.id}">
<table>
<c:if test="${msg != null}">
<tr>
<th colspan="2" style="color:red;max-width:400px;">${msg}</th>
</tr>
</c:if>
<tr>
<th colspan="2">字典维护</th>
</tr>
<tr>
<th>类别名</th>
<td><input type="text" name="code" value="${model.code}"></td>
</tr>
<tr>
<th>字典名</th>
<td><input type="text" name="name" value="${model.name}"></td>
</tr>
<tr>
<th>字典值</th>
<td><input type="text" name="value" value="${model.value}"></td>
</tr>
<tr>
<th colspan="2">
<input type="submit" value="保存">
<input type="button" onclick="backToList()" value="取消">
</th>
</tr>
</table>
</form>
<script>
function backToList(){
location.href = '${path}/dicts';
}
</script>
</body>
</html>
dicts.jsp 代码中使用了 jquery-3.1.1.min.js,大家可以从地址 https://code.jquery.com/jquery-3.1.1.min.js 中下载 jQuery,然后放在 webapp/static/ 目录下面。
部署和运行应用
将项目部署到 Tomcat 下,然后启动服务。服务器启动完成后,在浏览器中输入 http://localhost:8080/mybatis-spring/dicts 并访问,简单的字典管理操作界面便实现了,如图9-7所示。
点击【新增】,打开如图9-8所示的表单。


依次输入 “是否”、“是”、“1”,然后点击【保存】,保存后会跳转到字典管理界面,此时字典中就多了刚刚新增的数据。
点击刚刚新增的数据后面的【编辑】,打开如图9-9所示的界面。

将字典值改为 “是” 后点击【保存】,返回主界面后可以看到编辑后的效果。
点击新增数据后面的【删除】,会弹出提示框,询问是否删除该数据,点击【确定】后,该数据会被删除。
这些只是最简单的操作,也是业务中最普遍存在的功能。掌握基础功能开发后,结合前面几章学习的 MyBatis 的各种技巧后,我们就能实现各种各样的功能了。