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 对象的数据,这一点非常厉害,但是也引起疑问,不同类型的同级类,竟然能够互相存储。
划线
评论
复制
发布于: 刚刚阅读数: 3
andy
关注
还未添加个人签名 2019-11-21 加入
还未添加个人简介
评论