文章目录
0.前言
Mybatis 是我们常用的持久层框架之一,是我们熟悉的SSM中的“M”。
Mybatis 提供了灵活的数据库编程实现方式,提供了规范的数据库编程管理。相比古老的纯JDBC实现方式,也简化了数据库编程。
同时,由于SSM一直是经典,Mybatis的使用也成为程序员学习或工作中必不可少的环节。
在学习 Mybatis 之前,我们需要掌握一定的SQL基础,Spring、SpringMVC的一些基本用法。
1.基本用法
本文的 Mybatis 代码演示需要结合Spring项目进行测试,因此需要读者先自行创建Spring项目并根据实际情况自行控制各依赖版本。
1.1 依赖配置
(1)pom.xml 添加依赖
<!-- Mybatis框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- MySQL依赖项,仅运行时需要 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
(2)application配置
以下配置读者参考时要注意将数据库名、用户名和密码替换成自己实际的名或密码。
使用 application.properties 的同学可参考如下配置:
spring.datasource.url=jdbc:mysql://localhost:3306/DatabaseName?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
mybatis.mapper-locations=classpath:mapper/*.xml
使用 application.yml 的同学可参考如下配置:
mybatis:
type-aliases-package: cn.sharry.pojo.product.entity
mapper-locations: classpath:mybatis/mapper/*.xml
#mybatis缓存
configuration:
cache-enabled: true
(3)mybatis.config.xml 配置
如果读者使用的是传统的SSM实现方式,可能还需要使用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>
<settings>
<!-- #开启mybatis驼峰式命名规则自动转换 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer" />
<typeAlias alias="Long" type="java.lang.Long" />
<typeAlias alias="HashMap" type="java.util.HashMap" />
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
<typeAlias alias="ArrayList" type="java.util.ArrayList" />
<typeAlias alias="LinkedList" type="java.util.LinkedList" />
</typeAliases>
</configuration>
现在,由于有了SpringBoot 约定大于配置的特性,我们已逐步摒弃使用xml配置mybatis的方式。这种相对老式的配置可能还需要指定Mapper映射文件、高级数据库驱动等等,
这里先留个坑,若读者遇到这种老式项目的情况,可依情况再去查询。
(4)配置类
mybatis需要明确哪些接口是需要生成代理对象,在一些小Demo或小项目中,我们常在接口上添加@Mapper注解。但当接口较多时,为了提高效率,我们可以使用配置类来指定扫描
的接口所在的包:
/**MapperScan("路径")*/
@Configuration
@MapperScan("cn.sharry.astore.product.mapper")
public class MybatisConfiguration {
}
(5)配置测试
配置完成后,我们可以在测试类进行配置结果的测试:
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
@Autowired
DataSource dataSource;
/**
* 测试数据源是否能正常连接
* @throws SQLException
*/
@Test
void testGetConnection() throws SQLException {
dataSource.getConnection();
}
}
1.2 使用方式
在配置好mybatis后,我们通常有两种方式进行数据库编程:通过注解以及mapper.xml文件写sql。
(1)通过注解使用
举个例子,如果我们需要在某个Mapper执行插入操作,可以:
@Insert("insert into category values(null,#{name})")
void insert(String name);
其余标签@Select 、@Update、@Delete 用法与@Insert标签一致:
@[标签名]("[具体SQL语句]")
但是,由于实际开发中,一般表字段比较多,执行一些操作时sql语句可能会比较长,而且这种注解的方式不利于DBA的工作,因此我们一般比较少用注解的方式来进行数据库编程,此处对于这种实现方式的介绍也比较少,读者要有所侧重。
(2)通过mapper.xml使用
这是我们在学习、实际开发中用到更多的sql实现方式,需要在Mapper.xml中写SQL,例如:
<?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="cn.sharry.mapper.UserMenuMapper">
<!--结果集封装-->
<resultMap id="userMenus" type="cn.sharry.domain.SysUserMenu">
<id property="id" column="uid"></id>
<result property="name" column="username"></result>
<collection property="menus" ofType="cn.sharry.domain.SysMenu" autoMapping="true">
<id property="id" column="id"></id>
</collection>
</resultMap>
<!--查询用户菜单-->
<select id="findUserMenusById" resultMap="userMenus">
SELECT su.id uid, su.username username ,sm.*
FROM sys_users su
INNER JOIN sys_user_roles sur
ON su.id = sur.user_id
INNER JOIN sys_roles sr
ON sur.role_id = sr.id
INNER JOIN sys_role_menus srm
ON sr.id = srm.role_id
INNER JOIN sys_menus sm
ON srm.menu_id = sm.id
WHERE su.id = #{id}
</select>
</mapper>
这里提供一个空的Mapper.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">
<!--namespace应为对应Mapper接口的路径-->
<mapper namespace="">
</mapper>
当然,读者也可以通过官网等途径获取。
2. 单表增删查改
我们通过基本的单表增删查改来对Mybatis进行一个基本的入门,然后见简单介绍分页、连表供读者参考。
这里我们直接通过mapper.xml的举例来说明,至于所涉及的具体表、Controller、Service 等,篇幅有限,读者需自行创建并参考例子测试。
2.1 增
假设我们需要插入一个album相册的数据:
<!--插入数据-->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO album (name, description, sort)
VALUES (#{name}, #{description}, #{sort})
</insert>
useGeneratedKeys:允许JDBC自动生成主键;
keyProperty:指定主键
2.2 删
假设我们需要在album相册中根据id删除:
<delete id="deleteUserByIds">
DELETE FROM album
WHERE id in(
<foreach item="id" collection="array" open="("
close=")" separator=",">
#{id}
</foreach>
)
</delete>
foreach标签里包裹的是id数组,表示对id数组进行遍历
2.3 查
假设我们要查询 sys_users的列表:
<sql id="selectUser">
select id,username,password,salt,email,mobile,valid,deptId,createdTime,modifiedTime,createdUser,modifiedUser from sys_users
</sql>
<select id="findUserList" resultType="cn.sharry.domain.SysUser">
<include refid="selectUser"/>
<where>
<if test="username != null and username != ''">
and username = #{username}
</if>
</where>
</select>
sql标签:可存放sql片段,多用于可复用的语句;
where标签:去掉多余的and;
2.4 改
假设我们要修改album相册:
<update id="updateById">
UPDATE album
<set>
<if test="name != null">
name = #{name},
</if>
<if test="description != null">
description = #{description},
</if>
<if test=" sort != null">
sort = #{sort}
</if>
</set>
WHERE id = #{id}
</update>
2.5 分页
通过前面单表的增删查改后,这里再简单介绍一下分页查询与连表查询,均以例子体现:
<select id="listPage" resultMap="ListItemResultMap">
SELECT
<include refid="ListItemQueryFields" />
FROM
brand
ORDER BY id
LIMIT #{offset}, #{count}
</select>
2.6 连表
连表查询也是我们日常开发常用的,这里举个例子:
<!--结果集封装-->
<resultMap id="userMenus" type="cn.sharry.domain.SysUserMenu">
<id property="id" column="uid"></id>
<result property="name" column="username"></result>
<collection property="menus" ofType="cn.sharry.domain.SysMenu" autoMapping="true">
<id property="id" column="id"></id>
</collection>
</resultMap>
<!--查询用户菜单-->
<select id="findUserMenusById" resultMap="userMenus">
SELECT su.id uid, su.username username ,sm.*
FROM sys_users su
INNER JOIN sys_user_roles sur
ON su.id = sur.user_id
INNER JOIN sys_roles sr
ON sur.role_id = sr.id
INNER JOIN sys_role_menus srm
ON sr.id = srm.role_id
INNER JOIN sys_menus sm
ON srm.menu_id = sm.id
WHERE su.id = #{id}
</select>
通过上述列举的例子与简单说明,相信读者已基本了解了Mybatis如何使用。
3. 注意事项
本小节主要介绍一些使用Mybatis时的常见注意事项。
3.1 传参中$与#的区别
一般情况下,能用#{} 就用#{} !
#{} | ${} |
---|---|
预编译,默认为数据添加双引号,防止sql注入 | 当以字段名称为参数时才使用,一般不用 |
3.2 resultMap 与 resultType
我们执行查询时,通常结果会有两种:resultType 与 resultMap
使用resultType: 通常查询数量、或者表字段名与实体类字段名相同时,可直接使用resultType,例如:
<!--根据名称查询相册数量-->
<select id="selectCountByName" resultType="int">
SELECT count(*)
FROM album
WHERE name = #{name}
</select>
使用resultMap: 通常表字段中带有下划线_时,因为实体类字段默认需要驼峰命名,需要用resultMap来对字段进行指定,例如:
<!--查询品牌列表,具体查询语句略-->
<select id="selectList" resultMap="ListResultMap">
SELECT
<include refid="StandardQueryFields"/>
FROM pms_brand
ORDER BY
sort DESC ,id
</select>
<resultMap id="ListResultMap" type="cn.sharry.product.pojo.vo.BrandListItemVO">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="product_count" property="productCount"></result>
<result column="comment_count" property="commentCount"></result>
<result column="positive_comment_count" property="positiveCommentCount"></result>
</resultMap>
简单来说就是当实体类字段与数据库表字段不一致时就用resultMap
3.3 常用转义字符
字符 | 相当于 |
---|---|
> | > 大于 |
< | < 小于 |
& | & 号 |
3.4 缓存
Mybatis 默认开启一级缓存,在同一个SqlSession对象中查询相同的数据,可以实现数据的共享。
二级缓存:默认开启,需要手动标识使用,在SqlSessionFactory中共享数据,标识方式:
只需要在sql映射文件中添加,例如:
<?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="xxxxx">
<!--开启二级缓存-->
<cache/>
<!--以下是具体的Sql语句,略-->
....
</mapper>
4. 总结
Mybatis是目前常用的优秀的持久层框架,基于ORM,以对象的方式操作数据库。使用Mybatis通常需要先进行配置,再根据具体业务编写xml映射文件。基本的增删查改实现方式大多相对固定;分页、连表、模糊查询等查询也常用,读者应稍加练习。最后就是需要注意一下一些传参注意事项、标签的作用、缓存等。至于完整地实现一个项目的MVC,可能需要配合Controller、Service等,篇幅有限,这里不赘述。
我们下一篇见!