前言
这一节是JavaEE课设的第三节了,目前还奋战在持久层。这一节主要战场是mybatis框架,在开始这一节的内容前,我们先来简单回顾下前面两个小节我们都干了什么:
因此这一节,就应该开始编写mapper.xml文件了,也就是使用mybatis框架,给每个设计好的接口方法给予SQL实现。
知识点梳理
配置mybatis步骤
mybatis的配置首先需要拷贝相关组件并build path
他们。
接着需要在src目录下编写mybatis的配置文件,SqlMapConfig.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>
<!--扫描包,给类起别名,方便配置mapper文件-->
<typeAliases>
<package name="com.none.model"/>
</typeAliases>
<!--配置环境,环境可以有很多个,但是仅使用default-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="url" value="jdbc:mysql://localhost:3306/cinema?serverTimezone=UTC"/>
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="mysql"/>
</dataSource>
</environment>
</environments>
<!--扫描mapper文件,这里用package标签可以直接扫描整个包-->
<mappers>
<package name="com.none.mapper"/>
</mappers>
</configuration>
需要说明的是,整合ssm框架时,这些配置将会以bean的形式交由spring管理,目前就先使用配置进行持久层的开发测试。
在接下来,就可以为每个接口配置对应的mapper.xml
文件了。
在mapper包下建立mapper文件:
当然也可以选择将他们分开放置,但是需要注意的是,xml文件的位置需要和中心配置文件的扫描路径对应。接口的位置,需要和mapper文件中的名称空间一致。
多个参数的访问
mapper方法中传入多个参数,有多种方法进行处理,其中最常见的就是这三种:
- 将所有的参数封装进一个map中,仅传递一个map
- 在mapper接口方法的参数前使用@Param注解进行映射。也是这个课设最常使用的方法
- 在mapper xml中使用param1,param2等访问每一个参数
模糊查询
模糊查询需要使用百分号或者下划线用以当做占位符,但是mapper xml文件不方便进行拼接。
一种解决方法就是使用MySQL提供的拼接字符串函数CONCAT
。这样就可以拼接出一个模糊查询的目标串
举个例子,根据名称查询对应影厅,使用模糊查询
<select id="selectByName" resultType="room" parameterType="string">
SELECT
<include refid="content"></include>
FROM room
WHERE name LIKE CONCAT('%',#{value},'%');
</select>
子查询中不能使用limit
在当前版本的数据库中,不支持在子查询中使用limit的。可是面对业务需要(例如该项目中的查询票房topK的功能),有时不得不在二级查询结果中做出限制(例如要限制查询出的电影按照票房降序排列后取前k个的Id号码并以此获取这些电影)
这时使用子查询的一种写法:
<select id="selectTopK" resultMap="filmMap">
SELECT
<include refid="filmContent"></include>
FROM
JOIN film ON ids.film_id = id
film LEFT JOIN film_post ON film.id = film_post.film_id
WHERE film.id IN
(
SELECT plan.film_id from
record JOIN screening_plan plan ON record.plan_id = plan.id
WHERE record.time >= CONCAT(#{begin},' 00:00:00') AND record.time <= CONCAT(#{end},' 23:59:59')
GROUP BY plan.film_id
ORDER BY SUM(money) DESC
LIMIT 0,#{k}
) ;
</select>
然而这样写会遭到慈祥的警告。
所以可以将子查询换做一张表,使用连接来解决问题
<select id="selectTopK" resultMap="filmMap">
SELECT
<include refid="filmContent"></include>
FROM
(
SELECT plan.film_id from
record JOIN screening_plan plan ON record.plan_id = plan.id
WHERE record.time >= CONCAT(#{begin},' 00:00:00') AND record.time <= CONCAT(#{end},' 23:59:59')
GROUP BY plan.film_id
ORDER BY SUM(money) DESC
LIMIT 0,#{k}
) ids
JOIN film ON ids.film_id = id
LEFT JOIN film_post ON film.id = film_post.film_id;
</select>
不等号的替换
在各种ML文件中,尖括号都是一种敏感的存在,可同时它又正好是常用的大于号和小于号。如果想要正常的使用大于小于或是大于等于和小于等于关系,就需要使用替换符来代替左右尖括号。替换方式如下:
>
<==>>
<
<==><
>=
<==>>=
<=
<==><=
(其实在码这些替换符号时,如果不用代码块括起来,显示的就是转换过后的符号)
编写mapper并使用Junit进行测试
这一次并没有编写完所有的mapper,仅编写了其中的四个 (边复习边整理边写真的是太慢了,不过好在学的深刻)
先把所有的mapper放在这里:
FilmMapper
这个mapper有技术含量的(对博主来说),Film聚合了一个FilmPost集合,这需要用到结果集映射。这个问题有机会我们不妨单独使用一篇内容来讨论它。
另外有些查询需要联结多个表并需要需要用到分组、聚合函数等内容。(例如取topK的操作)
<?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.none.mapper.FilmMapper">
<sql id="content">
id,name,director,country,length,release_time,offline_time,language,introduction
</sql>
<sql id="noId">
name,director,country,length,release_time,offline_time,language,introduction
</sql>