【从零开始JavaEE课设】《影院系统》(四)搞定持久层

前言

这是课设制作总结的第四篇,目前仍旧奋战在持久层。前面三节分析了项目需求、编写了持久层mapper接口、实现了部分mapper接口的配置文件及测试。
这一节就来继续将剩下的mapper文件配置并测试完。

有关项目背景和model类设计可以查看第一节:【从零开始JavaEE课设】《影院系统》(一) 需求分析 数据库设计 后端model类

model层类涉及到的不多,仅有七个类且类间关系比较简单明确:
【从零开始JavaEE课设】《影院系统》(四)搞定持久层_第1张图片


知识点简结

resultMap配置

resultMap真的是一大神器,可以在其中清晰的表达类之间的对应包含关系,非常的方便。
对于这个项目来说,目前主要用到它来解决一对一和一对多关系。

一对一 和 一对多

在resultMap中使用association标签可以映射一对一的包含关系

例如,在放映计划中,一个放映计划关联了一个电影和一个房间,是两个一对一关系。
放映计划对应的resultMap:

<resultMap type="screeningPlan" id="planMap">
		<id column="spId" property="id"/>
		<result column="price" property="price"/>
		<result column="planTime" property="time"/>
		<result column="planDate" property="date"/>
		
		
		<association property="room" javaType="room">
			<id column="rId" property="id"/>
			<result column="seat" property="seat"/>
			<result column="roomName" property="name"/>
			<result column="type" property="type"/>
		association>
		
		<association property="film" javaType="film" resultMap="com.none.mapper.FilmMapper.filmMap">association>
	resultMap>

这个例子同时展示了如何使用已经映射好的map。对于关联关系一层一层传递的关系编写非常的友好。

映射在FilmMapper中的film:

<resultMap type="film" id="filmMap">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<result column="director" property="director"/>
		<result column="country" property="country"/>
		<result column="length" property="length"/>
		<result column="release_time" property="releaseTime"/>
		<result column="offline_time" property="offlineTime"/>
		<result column="language" property="language"/>
		<result column="introduction" property="introduction"/>
	
		<collection property="post" javaType="list" ofType="filmPost">
			<id column="pid" property="id"/>
			<result column="film_Id" property="filmId"/>
			<result column="dir" property="dir"/>
		collection>
			
	resultMap>

这里面又提到了如何进行一对多映射,电影和电影海报的关系就是一对多。这需要用到集合(collection)这个标签进行配置。
其中有三个常用属性:

  • property,表示这个集合映射到哪个成员
  • javaType,表示这个集合的类型
  • ofType,集合中元素的类型

另外,查询一对多关系时映射记得使用外联结,左右联结皆可,使用内联结可能会丢失一部分数据,mybatis会帮助我们自动将同一个主表内容映射成为一个同对象。
例如,查询所有的电影及其对应的海报对象,联结时的语句:

film LEFT OUTER JOIN film_post ON film.id = film_post.film_id

传递参数为集合,foreach标签

WHERE条件需要使用到IN判断时,往往需要传递一个集合作为参数。
这时需要使用到foreach标签进行处理

例如,查询一些电影对应的记录

mapper方法:

/*查询影片记录*/
public List<Record> selectByFilms(@Param("films") List<Film> films);

mapper文件:

<select id="selectByFilms" resultMap="recordMap"> 
	<include refid="select">include>
	WHERE film.id IN
	<foreach collection="films" index="index" item="film" open="(" separator="," close=")">
		#{film.id}
	foreach>
	;
select>

这里需要这几个参数:

  • collection,表示集合的类型,如果方法处使用了@Param注解则这里应该写注解中的映射名
  • index,代表迭代的次数或者映射中的键值
  • item,代表遍历到的元素
  • open,语句开始时的内容
  • close,语句结束时的内容
  • separator,参数见的分隔符

使用sql、include简化SQL语句

可以使用sql标签封装常用的sql片段,并在sql语句中使用include标签引用这些片段;

例如,需要查出的字段及其别名可以使用sql封装,并可以在具有嵌套结构时调用已经封装好的sql片段
例如,将相互联结的表的联结封装在一个sql片段中,编写select语句时就不需要表述千篇一律地表述表间的联结关系

如一个上映计划需要聚合一个电影和一个影厅,所以查询时需要将计划表联结电影表及影厅表:

<sql id="allContent">
	plan.id spId,plan.price price,plan.time planTime,plan.date planDate,
	room.id rId,room.seat seat,room.name roomName,room.type type,
	film.id fId,film.name filmName,film.director director,film.country country,film.length length,film.release_time release_time,film.offline_time offline_time,film.language language,film.introduction introduction,
	film_post.id pid,film_post.dir dir,film_post.film_id film_id 
sql>

<sql id="join">
	screening_plan plan JOIN film ON plan.film_id = film.id
	JOIN room ON room.id = plan.room_id
	LEFT JOIN film_post ON film_post.film_id = film.id
sql>

又如,一个购票记录需要组合一个放映计划:

<sql id="allContent">
	record.id reId,record.money reMoney,record.time reTime,record.code code,record.phone phone,record.seat_id seatId,
	<include refid="com.none.mapper.ScreeningPlanMapper.allContent">include>
sql>	
<sql id="join">
	record JOIN
	<include refid="com.none.mapper.ScreeningPlanMapper.join">include>
	ON record.plan_id = plan.id
sql>

mapper文件

Record




<mapper namespace="com.none.mapper.RecordMapper">


	<sql id="allContent">
		record.id reId,record.money reMoney,record.time reTime,record.code code,record.phone phone,record.seat_id seatId,
		<include refid="com.none.mapper.ScreeningPlanMapper.allContent">include>
	sql>	
	
	<sql id="noId">
		 money,time,code,phone,plan_id,seat_id
	sql>
	
	<sql id="join">
		record JOIN
		<include refid="com.none.mapper.ScreeningPlanMapper.join">include>
		ON record.plan_id = plan.id
	sql>
	
	<sql id="select">
		SELECT
		<include refid="allContent">include>
		FROM
		<include refid="join">include>
	sql>
	
	<resultMap type="record" id="recordMap">
		<id column="reId" property="id"/>
		<result column="reMoney" property="money"/>
		<result column="reTime" property="time"/>
		<result column="code" property="code"/>
		<result column="phone" property="phone"/>
		<result column="seatId" property="seatId"/>
		
		<association property="plan" resultMap="com.none.mapper.ScreeningPlanMapper.planMap">association>
	resultMap>

	<insert id="insertRecord" parameterType="record">
		INSERT INTO record
		(<include refid="noId">include>)
		VALUE
		(#{money},#{time},#{code},#{phone},#{plan.id},#{seatId});
	insert>
	
	<delete id="deleteById" parameterType="int">
		DELETE FROM record WHERE id = #{value};
	delete>
	
	<update id="updateRecord" parameterType="record">
		UPDATE record
		<set>
			<if test="#{plan.id} != null">
				plan_id = #{plan.id},
			if>
			<if test="#{money} != null">
				money = #{money},
			if>
			<if test="#{time} != null">
				time = #{time},
			if>
			<if test="#{phone} != null">
				phone = #{phone},
			if>
			<if test="#{seatId} != null">
				seat_id = #{seatId},
			if>
			<if test="#{code} != null">
				code = #{code},
			if>
		set>
		WHERE id = #{id};
	update>
	
	
	<select id="selectAll" resultMap="recordMap">
		<include refid="select">include>
		;
	select>
	
	<select id="selectByPhone" resultMap="recordMap" parameterType="string">
		<include refid="select">include>
		WHERE record.phone = #{value};
	select>
	
	<select id="selectByTime" resultMap="recordMap">
		<include refid="select">include>
		WHERE record.time BETWEEN #{begin} AND #{end};
	select>
	
	<select id="selectByFilms" resultMap="recordMap"> 
		<include refid="select">include>
		WHERE film.id IN
		<foreach collection="films" index="index" item="film" open="(" separator="," close=")">
			#{film.id}
		foreach>
		;
	select>
	
	<select id="selectByRooms" resultMap="recordMap">
		<include refid="select">include>
		WHERE room.id IN
		<foreach collection="rooms" index="index" item="room" open="(" separator="," close=")">
			#{room.id}
		foreach>
		;
	select>
	
	<select id="selectByRoomsAndFilms" resultMap="recordMap">
		<include refid="select">include>
		WHERE room.id IN
		<foreach collection="rooms" index="index" item="room" open="(" separator="," close=")">
			#{room.id}
		foreach>
		AND film.id IN
		<foreach collection="films" index="index" item="film" open="(" separator="," close=")">
			#{film.id}
		foreach>
		
	select>
mapper>

ScreeningPlan




<mapper namespace="com.none.mapper.ScreeningPlanMapper">

	<resultMap type="screeningPlan" id="planMap">
		<id column="spId" property="id"/>
		<result column="price" property="price"/>
		<result column="planTime" property="time"/>
		<result column="planDate" property="date"/>
		
		<association property="room" javaType="room">
			<id column="rId" property="id"/>
			<result column="seat" property="seat"/>
			<result column="roomName" property="name"/>
			<result column="type" property="type"/>
		association>
		
		<association property="film" javaType="film" resultMap="com.none.mapper.FilmMapper.filmMap">association>
	resultMap>

	<sql id="allContent">
		plan.id spId,plan.price price,plan.time planTime,plan.date planDate,
		room.id rId,room.seat seat,room.name roomName,room.type type,
		film.id fId,film.name filmName,film.director director,film.country country,film.length length,film.release_time release_time,film.offline_time offline_time,film.language language,film.introduction introduction,
		film_post.id pid,film_post.dir dir,film_post.film_id film_id 
	sql>
	
	<sql id="join">
		screening_plan plan JOIN film ON plan.film_id = film.id
		JOIN room ON room.id = plan.room_id
		LEFT JOIN film_post ON film_post.film_id = film.id
	sql>
	
	<sql id="noId">
		price,time,date,room_id,film_id
	sql>
	<insert id="insertPlan">
		INSERT INTO screening_plan
		(<include refid="noId">include>)
		VALUE
		(#{price},#{time},#{date},#{room.id},#{film.id});
	insert>
	
	<update id="updatePlan">
		UPDATE screening_plan
		<set>
			<if test="#{price} != null">
				price = #{price},
			if>
			<if test="#{time} != null">
				time = #{time},
			if>
			<if test="#{date} != null">
				date = #{date},
			if>
			<if test="#{room.id} != null">
				room_id = #{room.id},
			if>
			<if test="#{film.id} != null">
				film_id = #{film.id},
			if>
		set>
		WHERE id = #{id};
	update>
	
	<delete id="deleteById">
		DELETE FROM screening_plan WHERE id = #{value};
	delete>
	
	<select id="selectNearby" resultMap="planMap">
		SELECT 
		<include refid="allContent">include>
		FROM
		<include refid="join">include>
		WHERE
		plan.date BETWEEN #{nowDate} AND #{endDate}
		AND
		plan.time BETWEEN #{nowTime} AND #{endTime};
	select>
	
	<select id="selectPlans" resultMap="planMap">
		SELECT
		<include refid="allContent">include>
		FROM
		<include refid="join">include>
		WHERE
		plan.film_id = #{film.id}
		AND
		plan.date = #{date}
		AND
		plan.time >= #{time};
	select>
	
	<select id="selectById" resultMap="planMap">
		SELECT
		<include refid="allContent">include>
		FROM
		<include refid="join">include>
		WHERE plan.id = #{value};
	select>
mapper>

Staff




<mapper namespace="com.none.mapper.StaffMapper">

	<sql id="content">
		 id,name,id_card idCard,password
	sql>
	
	
	<select id="selectByIdCard" parameterType="String" resultType="staff">
		SELECT
		<include refid="content">include>
		FROM staff
		WHERE id_card = #{value};
	select>

mapper>

Vip



<mapper namespace="com.none.mapper.VipMapper">
	
	<sql id="noId">
		code,discount,money,password,phone,name,birthday,due_time
	sql>
	
	<sql id="content">
		id,
		<include refid="noId">include>
	sql>
	
	<sql id="value">
		#{code},#{discount},#{money},#{password},#{phone},#{name},#{birthday},#{dueTime}
	sql>
	
	<insert id="insertVip" parameterType="vip">
		INSERT INTO vip
		(<include refid="noId">include>)
		VALUE
		(<include refid="value">include>);
	insert>
	
	<delete id="deleteById" parameterType="int">
		DELETE FROM vip WHERE id = #{value};
	delete>
	
	<update id="updateVip" parameterType="vip">
		UPDATE vip 
		<set>
			<if test="#{name} != null">
				name = #{name},
			if>
			<if test="#{birthday} != null">
				birthday = #{birthday},
			if>
			<if test="#{dueTime} != null">
				due_time = #{dueTime},
			if>
			<if test="#{password} != null">
				password = #{password},
			if>
			<if test="#{phone} != null">
				phone = #{phone},
			if>
			<if test="#{code} != null">
				code = #{code},
			if>
			<if test="#{discount} != null">
				discount = #{discount},
			if>
			<if test="#{money} != null">
				money = #{money},
			if>
		set>
		WHERE id = #{id};
	update>
	
	<select id="selectVip" resultType="vip" parameterType="string">
		SELECT 
		<include refid="content">include>
		FROM vip WHERE 
		code = #{value}
		OR
		phone = #{value};
	select>
mapper>

测试类

其他的mapper和对应测试代码在上一篇:
【从零开始JavaEE课设】《影院系统》(三)配置mybatis框架,编写mapper文件并测试(附mybatis知识点)

RecordTest

package com.none.tests;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.none.mapper.FilmMapper;
import com.none.mapper.RecordMapper;
import com.none.mapper.RoomMapper;
import com.none.mapper.ScreeningPlanMapper;
import com.none.model.Film;
import com.none.model.Record;
import com.none.model.ScreeningPlan;
import com.none.util.DateUtil;
import com.none.util.MapperUtil;

public class RecordTest {

	RecordMapper mapper = (RecordMapper) MapperUtil.getMapper(RecordMapper.class);
	ScreeningPlanMapper sm = (ScreeningPlanMapper) MapperUtil.getMapper(ScreeningPlanMapper.class);
	FilmMapper fm = (FilmMapper) MapperUtil.getMapper(FilmMapper.class);
	RoomMapper rm = (RoomMapper) MapperUtil.getMapper(RoomMapper.class);
	
	@Test
	public void insert()
	{
		ScreeningPlan plan = sm.selectById(2);
		Record record = new Record();
		record.setPlan(plan);
		record.setCode("67987");
		record.setMoney(35);
		record.setSeatId(33);
		record.setPhone("10086");
		record.setTime(DateUtil.getCurrentDateTime());
		
		mapper.insertRecord(record);
		
		MapperUtil.commit();
	}
	
	@Test
	public void delete()
	{
		mapper.deleteById(5);
		MapperUtil.commit();
	}
	
	@Test
	public void update()
	{
		ScreeningPlan plan = sm.selectById(2);
		Record record = new Record();
		record.setPlan(plan);
		record.setCode("67987");
		record.setMoney(35);
		record.setSeatId(33);
		record.setPhone("10010");
		record.setTime(DateUtil.getCurrentDateTime());
		record.setId(6);
		mapper.updateRecord(record);
		
		MapperUtil.commit();
	}
	
	@Test
	public void selectAll()
	{
		List<Record> list = mapper.selectAll();
		for(Record r: list)
		{
			System.out.println(r);
		}
	}
	
	@Test
	public void selectByNumber()
	{
		System.out.println(mapper.selectByPhone("10010"));
	}
	
	@Test
	public void selectByTime()
	{
		System.out.println(mapper.selectByTime("2020-01-01 00:00:00", DateUtil.getCurrentDateTime()));
	}
	
	@Test
	public void selectList()
	{
		//System.out.println(fm.selectOnLine(DateUtil.getCurrentDate()));
		//List list = mapper.selectByFilms(fm.selectByName("穿越"));
		List<Record> list = mapper.selectByRoomsAndFilms(rm.selectByName("测试厅1"),fm.selectByName("星际穿越"));
		for(Record r : list)
		{
			System.out.println(r);
		}
	}
}


ScreeningPlanTest

package com.none.tests;

import java.util.List;

import org.junit.Test;

import com.none.mapper.FilmMapper;
import com.none.mapper.RoomMapper;
import com.none.mapper.ScreeningPlanMapper;
import com.none.model.Film;
import com.none.model.Room;
import com.none.model.ScreeningPlan;
import com.none.util.DateUtil;
import com.none.util.MapperUtil;

public class ScreeningPlanTest {

	
	ScreeningPlanMapper mapper = (ScreeningPlanMapper) MapperUtil.getMapper(ScreeningPlanMapper.class);
	RoomMapper rm = (RoomMapper) MapperUtil.getMapper(RoomMapper.class);
	FilmMapper fm = (FilmMapper) MapperUtil.getMapper(FilmMapper.class);
	@Test
	public void insert()
	{
		Room room = rm.selectByName("测试").get(0);
		Film film = fm.selectByName("哪吒").get(0);
		ScreeningPlan plan = new ScreeningPlan();
		plan.setTime("15:30:00");
		plan.setDate("2020-06-25");
		plan.setPrice(50);
		plan.setFilm(film);
		plan.setRoom(room);
		mapper.insertPlan(plan);
		MapperUtil.commit();
	}
	
	@Test
	public void update()
	{
		Room room = rm.selectByName("测试").get(0);
		Film film = fm.selectByName("哪吒").get(0);
		ScreeningPlan plan = new ScreeningPlan();
		plan.setTime("15:30:00");
		plan.setDate("2020-06-25");
		plan.setPrice(25);
		plan.setFilm(film);
		plan.setRoom(room);
		plan.setId(4);
		mapper.updatePlan(plan);
		MapperUtil.commit();
	}
	
	@Test
	public void delete()
	{
		mapper.deleteById(4);
		MapperUtil.commit();
	}
	
	@Test
	public void selectNear()
	{
		List<ScreeningPlan> list = mapper.selectNearby(DateUtil.getCurrentTime(), "23:59:59", DateUtil.getCurrentDate(), "2020-07-20");
		for(ScreeningPlan p : list)
		{
			System.out.println(p);
		}
	}
	
	@Test
	public void selectPlan() {
		Film film = fm.selectByName("穿越").get(0);
		
		List<ScreeningPlan> list = mapper.selectPlans(film, "2020-06-25", "00:00:00");
		
		for(ScreeningPlan p : list)
		{
			System.out.println(p);
		}
	}
	
	@Test
	public void selectOne()
	{
		ScreeningPlan plan = mapper.selectById(2);
		System.out.println(plan);
	}
}

VipTest

package com.none.tests;

import org.junit.Test;

import com.none.mapper.StaffMapper;
import com.none.util.MapperUtil;

public class StaffTest {
	
	StaffMapper mapper = (StaffMapper) MapperUtil.getMapper(StaffMapper.class);
	@Test
	public void select() {
		
		System.out.println(mapper.selectByIdCard("123456789"));
	}
}

StaffTest

package com.none.tests;

import org.junit.Test;

import com.none.mapper.VipMapper;
import com.none.model.Vip;
import com.none.util.MapperUtil;

public class VipTest {
	
	VipMapper mapper = (VipMapper) MapperUtil.getMapper(VipMapper.class);
	
	@Test
	public void insert()
	{
		Vip vip = new Vip();
		vip.setBirthday("2001-06-02");
		vip.setCode("987654321");
		vip.setDiscount(0.5);
		vip.setDueTime("9999-12-31");
		vip.setMoney(99999);
		vip.setPassword("123456");
		vip.setPhone("1333333333333");
		vip.setName("张三");
		
		mapper.insertVip(vip);
		MapperUtil.commit();
	}
	
	@Test
	public void update()
	{
		Vip vip = new Vip();
		vip.setBirthday("2001-06-02");
		vip.setCode("123456789");
		vip.setDiscount(0.5);
		vip.setDueTime("9999-12-31");
		vip.setMoney(99999);
		vip.setPassword("123456");
		vip.setPhone("15555555555");
		vip.setName("李四");
		vip.setId(1);
		
		mapper.updateVip(vip);
		MapperUtil.commit();
	}
	
	@Test
	public void delete()
	{
		mapper.deleteById(3);
		MapperUtil.commit();
	}
	
	@Test
	public void select()
	{
		System.out.println(mapper.selectVip("123456789"));
	}
}


前面几节

  • 【从零开始JavaEE课设】《影院系统》(一) 需求分析 数据库设计 后端model类
  • 【从零开始JavaEE课设】《影院系统》(二)编写持久层Mapper接口
  • 【从零开始JavaEE课设】《影院系统》(三)配置mybatis框架,编写mapper文件并测试(附mybatis知识点)

你可能感兴趣的:(JavaWeb,mybatis)