写点什么

MyBatis 之识别器

作者:andy
  • 2022-10-27
    北京
  • 本文字数:2913 字

    阅读完需:约 10 分钟

一、多表重复字段的问题


在数据库设计中,会出现多个不同的事物之间有相同的信息。书礼物表中存在有名称、描述、作者,而纪念品礼物表中存在有名称、描述、产地。其中,名称和描述都是两个表共有的属性信息,而只不过书礼物表有作者,纪念品礼物表有产地。那么,对于这样的情况,该如何合理设计数据库表呢?这个问题暂时留着,本文章主要阐述的不是这一个问题。


书礼物表:


create table giftbook(	gid		int		auto_increment,    name	varchar(30)		not null,    description		varchar(255),    author	varchar(30),    constraint pk_gid primary key(gid))engine InnoDB;
复制代码


纪念品礼物表:


create table giftsouvenir(	gid		int		auto_increment,    name	varchar(30)		not null,    description		varchar(255),    origin	varchar(255),    constraint pk_gid primary key(gid))engine InnoDB;
复制代码


二、MyBatis 识别器的引入


实际上,一旦类似的事物不断增加。那么,就要不断建立新表。因此,可以建立一张表,通过标志位判断各自存储的内容即可。


礼物表:


create table gift(	gid		int		auto_increment,    name	varchar(30)		not null,    description		varchar(255),    cost	double,    flag	varchar(30)		not null,    author	varchar(30),    origin	varchar(255),    constraint pk_gid primary key(gid))engine InnoDB;
复制代码


在项目开发中,需要将数据库数据转化为 VO 对象。那么,我们仍然不可能去建立多个 VO,让后编写重复字段。因此,可以建立 Gift 父类,把共同属性和标志位的属性添加上,剩下的 GiftBook 和 GiftSouvenir 子类继承父类,再各自增加属于自己的属性。


Gift 父类:


package org.fuys.owndb.vo;import java.io.Serializable;@SuppressWarnings("serial")public class Gift implements Serializable {	private Integer gid;	private String name;	private String description;	private Double cost;	private String flag;}
复制代码


package org.fuys.owndb.vo;import java.io.Serializable;@SuppressWarnings("serial")public class GiftBook extends Gift implements Serializable {		private String author;}
复制代码


GiftSouvenir 子类:


package org.fuys.owndb.vo;import java.io.Serializable;@SuppressWarnings("serial")public class GiftBook extends Gift implements Serializable {	private String author;}
复制代码


那么,建立好基础类之后,需要在核心内容配置文件中添加类的别人,以便引用。


<typeAliases>		<typeAlias type="org.fuys.owndb.vo.Gift" alias="Gift"/>		<typeAlias type="org.fuys.owndb.vo.GiftBook" alias="GiftBook"/>		<typeAlias type="org.fuys.owndb.vo.GiftSouvenir" alias="GiftSouvenir"/>	</typeAliases>
复制代码


随后添加映射文件。


<mappers>		<mapper resource="org/fuys/owndb/vo/mapping/Gift.xml"/>	</mappers>
复制代码


在映射文件中,配置信息,但是需要注意的是:resultMap 的编写,添加识别器 discriminator。


Gift.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="org.fuys.owndb.vo.mapping.Gift">	<resultMap type="Gift" id="GiftResultMap">		<id column="gid" property="gid" />		<result column="name" property="name" />		<result column="description" property="description" />		<result column="cost" property="cost" />		<discriminator javaType="java.lang.String" column="flag">			<case value="book" resultType="GiftBook">				<result column="author" property="author" />			</case>			<case value="souvenir" resultType="GiftSouvenir">				<result column="origin" property="origin" />			</case>		</discriminator>	</resultMap>	<insert id="insertGiftBook" parameterType="GiftBook" keyProperty="gid" useGeneratedKeys="true">		INSERT INTO		gift(name,description,cost,flag,author)		VALUES(#{name},#{description},#{cost},"book",#{author})	</insert>	<select id="selectGiftBookList" parameterType="GiftBook" resultMap="GiftResultMap">		SELECT gid,name,description,cost,flag,author,origin		FROM gift		<where>			<if test="gid !=null">				and gid = #{gid}			</if>			<if test="name !=null">				and name LIKE CONCAT(CONCAT("%",#{name}),"%")			</if>			<if test="description !=null">				and description LIKE CONCAT(CONCAT("%",#{description}),"%")			</if>			<if test="cost !=null">				and cost = #{cost}			</if>			<if test="flag !=null">				and flag = #{flag}			</if>		</where>	</select></mapper>
复制代码


测试程序:


package org.fuys.owndb.test;import java.util.List;import java.util.Random;import org.fuys.owndb.model.MyBatisSqlSessionFactory;import org.fuys.owndb.vo.Gift;import org.fuys.owndb.vo.GiftBook;import org.fuys.owndb.vo.GiftSouvenir;import org.junit.Test;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import junit.framework.TestCase;public class TestDiscriminator {	private Logger logger = LoggerFactory.getLogger(TestDiscriminator.class);	@Test	public void testInsert() {				GiftBook book = new GiftBook();		book.setName("zero to one " + new Random().nextInt(99));		book.setDescription("It's about company.");		book.setCost(79.4);		book.setFlag("book");		book.setAuthor("Peter Thiel");		int lenA = MyBatisSqlSessionFactory.getSqlSession().insert("org.fuys.owndb.vo.mapping.Gift.insertGiftBook", book);		MyBatisSqlSessionFactory.getSqlSession().commit();		TestCase.assertEquals(lenA, 1);		logger.info(String.valueOf(lenA));		logger.info(book.toString());	}	@Test	public void testSelectList() {		GiftBook book = new GiftBook();		book.setAuthor("Peter Thiel");		List<GiftBook> bookList = MyBatisSqlSessionFactory.getSqlSession().selectList("org.fuys.owndb.vo.mapping.Gift.selectGiftBookList", book);		TestCase.assertNotNull(bookList);		for(int x=0;x<bookList.size();x++){			Gift gift = bookList.get(x);			if(gift instanceof Gift){				logger.info("gift --> " + x);			}			if(gift instanceof GiftBook){				logger.info("giftBook --> " + x);			}			if(gift instanceof GiftSouvenir){				logger.info("giftSouvenir --> " + x);			}		}		logger.info(bookList.toString());	}}
复制代码


发现:


程序验证之后,发现一个问题,对于查询 GiftBook 数据,我将所有的 Gift 数据全部查询出来,在 GiftBook 集合中,竟然包含 GiftSouvenir 对象的数据,这一点非常厉害,但是也引起疑问,不同类型的同级类,竟然能够互相存储。


用户头像

andy

关注

还未添加个人签名 2019-11-21 加入

还未添加个人简介

评论

发布
暂无评论
MyBatis之识别器_andy_InfoQ写作社区