一 需求分析
1 分析
在项目中会有很多的下拉框,这些下拉框的特点,就是以键值对的形式存在,其中 value(如 id:1,2… ),key(展示给用户的内容),数据库中可通过 value 寻找对应的 key,对于固定的内容可使用数据字典形式进行填写,防止出错。
实现方案:
1.直接硬编码写在html代码中(升级复杂,维护困难)
2.为每个下拉框都设计一个表,然后提供CRUD功能(表单中下拉框很多,内容相似,没必要每个都配,只特殊情况下使用)
3.使用数据字典的方式(维护项目中所有的下拉列表)
二 表设计
1 概述
sys_dict_type 中主要存储项目中有哪些下拉框,sys_dict_data 中主要存储项目中下拉框对应的option的具体内容,两张表通过 dict_type 进行关联,查询时可通过下拉框名称“性别”于 sys_dict_type 表中搜索 dict_name 为“性别”的记录的 dict_type 字段,通过该字段到 sys_dict_data 表中获取需要展示的 key(dict_value) 与 value(dict_label),通过 dict_sort 可对下拉框中内容进行排序,如:
2 字典类型表 sys_dict_type
所有程序中的select,该表中 dict_type 需唯一
字段 | 描述 |
dict_id | 主键 |
dict_name | 字典名称(例:性别) |
dict_type | 字典类型(例:sex) |
remark | 备注(例:性别) |
3 字典数据表 sys_dict_data
所有程序中的select所对应的option,例:< option value=“1”>女< /option>,其中键值为1,标签为女
字段 | 描述 |
dict_code | 主键 |
dict_type | 字典类型 |
dict_label | 字典标签(例:女) |
dict_value | 字典键值(例:1) |
dict_sort | 字典排序(对下拉列表数据进行排序) |
remark | 备注 |
4 客户表 t_customer
客户表中存储 source_value 与 school_value 通过关联上表,获取所需的数据,建议使用左连接防止由于字段NULL时查询丢失数据
字段 | 描述 |
id | 主键 |
name | 客户名称 |
phone | 联系方式 |
source_value | 常住地 |
school_value | 最高学历 |
三 项目搭建
1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.tj</groupId>
<artifactId>sys-dict-demo</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.13.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<druid.version>1.2.6</druid.version>
<mybatis-spring-boot.version>2.1.4</mybatis-spring-boot.version>
<fastjson.version>1.2.76</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot集成thymeleaf模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- MyBatis 逆向工程插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>false</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
2 主启动类 – SysDictApp
@SpringBootApplication
// mapper包不在同一目录下,填写路径(所有mapper接口)
@MapperScan("cn.tj.**.mapper")
public class SysDictApp {
public static void main(String[] args) {
SpringApplication.run(SysDictApp.class,args);
}
}
3 yml配置文件 – application.yml
# Spring配置
spring:
# 模板引擎
thymeleaf:
mode: HTML
encoding: utf-8
# 禁用缓存
cache: false
# 数据库配置信息
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/zd?serverTimezone=GMT%2B8
username: root
password: root
# MyBatis
mybatis:
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/*Mapper.xml
# 日志配置
logging:
level:
cn.tj: debug
org.springframework: warn
server:
port: 80
4 实体类 – SysDictType
@Getter
@Setter
public class SysDictType{
private Long dictId;
private String dictName;
private String dictType;
private String remark;
}
5 实体类 – SysDictData
@Getter
@Setter
public class SysDictData {
private Long dict_code;
private Integer dict_sort;
private String dict_label;
private String dict_value;
private String dict_type;
private String remark;
}
6 实体类 – Customer
@Setter
@Getter
public class Customer {
private Long id;
private String name;
private String phone;
// 关联字段
private SysDictData sourceType;
private SysDictData schoolType;
}
7 数据库表 – sys_dict_type
CREATE TABLE `sys_dict_type` (
`dict_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典主键',
`dict_name` varchar(100) DEFAULT '' COMMENT '字典名称',
`dict_type` varchar(100) DEFAULT '' COMMENT '字典类型',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_id`),
UNIQUE KEY `dict_type` (`dict_type`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 COMMENT='字典类型表';
8 数据库表 – sys_dict_data
CREATE TABLE `sys_dict_data` (
`dict_code` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典编码',
`dict_sort` int(4) DEFAULT '0' COMMENT '字典排序',
`dict_label` varchar(100) DEFAULT '' COMMENT '字典标签',
`dict_value` varchar(100) DEFAULT '' COMMENT '字典键值',
`dict_type` varchar(100) DEFAULT '' COMMENT '字典类型',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_code`)
) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8 COMMENT='字典数据表';
9 数据库表 – t_customer
CREATE TABLE `t_customer` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`phone` varchar(255) DEFAULT NULL,
`source_value` bigint(20) DEFAULT NULL,
`school_value` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
10 mapper接口 – SysDictTypeMapper
public interface SysDictTypeMapper {
List<SysDictType> selectAll();
int getCountByDictType(String dictType);
void insert(SysDictType sysDictType);
SysDictType get(Long dictId);
void update(SysDictType sysDictType);
SysDictType getByDictType(String dictType);
}
11 mapper接口 – SysDictDataMapper
public interface SysDictDataMapper {
int deleteByPrimaryKey(Long dict_code);
int insert(SysDictData record);
SysDictData selectByPrimaryKey(Long dict_code);
List<SysDictData> selectAll();
int updateByPrimaryKey(SysDictData record);
List<SysDictData> queryByDictType(String dictType);
}
12 mapper接口 – CustomerMapper
public interface CustomerMapper {
List<Customer> selectAll();
void insert(Customer customer);
void update(Customer customer);
Customer get(Long id);
}
13 mapper.xml – SysDictTypeMapper
<?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.tj.mapper.SysDictTypeMapper">
<resultMap id="sysDictTypeResult" type="cn.tj.domain.SysDictType">
<result column="dict_id" property="dictId"/>
<result column="dict_name" property="dictName"/>
<result column="dict_type" property="dictType"/>
<result column="remark" property="remark"/>
</resultMap>
<insert id="insert" keyProperty="dictId" useGeneratedKeys="true">
insert into sys_dict_type(dict_name, dict_type, remark) values (#{dictName},#{dictType},#{remark})
</insert>
<update id="update">
update sys_dict_type set
dict_name = #{dictName},
remark = #{remark}
where dict_id = #{dictId}
</update>
<select id="selectAll" resultMap="sysDictTypeResult">
select dict_id, dict_name, dict_type, remark from sys_dict_type
</select>
<select id="getCountByDictType" resultType="java.lang.Integer">
select count(*) from sys_dict_type where dict_type=#{dictType}
</select>
<select id="get" resultMap="sysDictTypeResult">
select dict_id, dict_name, dict_type, remark from sys_dict_type
where dict_id=#{dictId}
</select>
<select id="getByDictType" resultMap="sysDictTypeResult">
select dict_id, dict_name, dict_type, remark from sys_dict_type
where dict_type=#{dictType}
</select>
</mapper>
14 mapper.xml – SysDictDataMapper
<?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.tj.mapper.SysDictDataMapper" >
<resultMap id="BaseResultMap" type="cn.tj.domain.SysDictData" >
<id column="dict_code" property="dict_code" />
<result column="dict_sort" property="dict_sort" />
<result column="dict_label" property="dict_label" />
<result column="dict_value" property="dict_value" />
<result column="dict_type" property="dict_type" />
<result column="remark" property="remark" />
</resultMap>
<delete id="deleteByPrimaryKey" >
delete from sys_dict_data
where dict_code = #{dict_code}
</delete>
<insert id="insert" >
insert into sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, remark
)
values (#{dict_code}, #{dict_sort}, #{dict_label}, #{dict_value}, #{dict_type}, #{remark}
)
</insert>
<update id="updateByPrimaryKey" >
update sys_dict_data
set dict_sort = #{dict_sort},
dict_label = #{dict_label},
dict_value = #{dict_value},
remark = #{remark}
where dict_code = #{dict_code}
</update>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" >
select dict_code, dict_sort, dict_label, dict_value, dict_type, remark
from sys_dict_data
where dict_code = #{dict_code}
</select>
<select id="selectAll" resultMap="BaseResultMap" >
select dict_code, dict_sort, dict_label, dict_value, dict_type, remark
from sys_dict_data
</select>
<select id="queryByDictType" resultMap="BaseResultMap">
select dict_code, dict_sort, dict_label, dict_value, dict_type, remark
from sys_dict_data
where dict_type=#{dictType}
order by dict_sort asc
</select>
</mapper>
15 mapper.xml – CustomerMapper
<?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.tj.mapper.CustomerMapper">
<resultMap id="CustomerResult" type="cn.tj.domain.Customer">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="phone" property="phone"/>
<result column="s1_label" property="sourceType.dict_label"/>
<result column="s2_label" property="schoolType.dict_label"/>
<result column="s1_value" property="sourceType.dict_value"/>
<result column="s2_value" property="schoolType.dict_value"/>
</resultMap>
<select id="selectAll" resultMap="CustomerResult">
select c.id,c.name,c.phone,s1.dict_value s1_value,s1.dict_label s1_label,s2.dict_value s2_value,s2.dict_label s2_label from t_customer c
left join sys_dict_data s1 on (c.source_value = s1.dict_value and s1.dict_type="sourceType")
left join sys_dict_data s2 on (c.school_value = s2.dict_value and s2.dict_type="schoolType")
</select>
<insert id="insert">
insert into t_customer(name,phone,source_value,school_value)
values (#{name},#{phone},#{sourceType.dict_value},#{schoolType.dict_value})
</insert>
<update id="update">
update t_customer set
name = #{name},
phone = #{phone},
source_value = #{sourceType.dict_value},
school_value = #{schoolType.dict_value}
where id = #{id}
</update>
<select id="get" resultMap="CustomerResult">
select c.id,c.name,c.phone,s1.dict_value s1_value,s1.dict_label s1_label,s2.dict_value s2_value,s2.dict_label s2_label from t_customer c
left join sys_dict_data s1 on (c.source_value = s1.dict_value and s1.dict_type="sourceType")
left join sys_dict_data s2 on (c.school_value = s2.dict_value and s2.dict_type="schoolType")
where id = #{id}
</select>
</mapper>