说明
- 后端提供包含省、市、区的地址数据,供前端地址选择组件渲染
数据库设计
- 行政区划的数据截止2020年12月,数据来源见文末附录。
表结构
CREATE TABLE `address` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`parent` int NOT NULL COMMENT '父类城市编码',
`address` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '地址名',
`address_type` int NOT NULL COMMENT '地址类型',
`code` int NOT NULL COMMENT '地址编码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
表数据文件,下载地址:
- Gitee:https://gitee.com/minghue/csdn_note_document
- GitCode:https://gitcode.net/MINGHUE/csdn_note_document
文件路径:
根目录/csdn_address
注:数据来源中,没有西沙区和南沙区(三沙市)的行政区划代码。所以在数据库中将这两个区的code指定成了-1。
实体信息
package com.minghue.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
/**
* @author MING_HUE
* @date 2022/11/8 10:00
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
@Entity
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Address implements Serializable {
private static final long serialVersionUID = -2759732463901224816L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@TableId(type = IdType.AUTO)
@JsonIgnore
private Integer id;
/**
* 父类code,省_固定86(中国国家编码)
*/
private Integer parent;
/**
* 地址
*/
private String address;
/**
* 地址类型:1省 2市 3区
*/
@JsonIgnore
private Integer addressType;
/**
* 编码
*/
private Integer code;
/**
* 下级城市信息
*/
@TableField(exist = false)
@Transient
private List<Address> junior;
}
数据处理
Java
/**
* @return 城市信息_含省市区
*/
public List<Address> all() {
//①
List<Address> allData = this.addressService.list();
//过滤出全部省份信息
List<Address> result = allData.stream().filter(address -> address.getAddressType() == 1).collect(Collectors.toList());
result.forEach(pro -> {
//组装市信息
List<Address> city = allData.stream().filter(address -> address.getAddressType() == 2 && address.getParent().equals(pro.getCode())).collect(Collectors.toList());
if (!city.isEmpty()) {
pro.setJunior(city);
}
//组装区信息
city.forEach(ci -> {
List<Address> area = allData.stream().filter(address -> address.getAddressType() == 3 && address.getParent().equals(ci.getCode())).collect(Collectors.toList());
if (!area.isEmpty()) {
ci.setJunior(area);
}
});
});
return result;
}
/**
* 地址列表
*
* @param code 上级城市编码,null或86时,查询中国数据
* @param type 结果城市类型:1省2市3区
* @return 地址列表
*/
public List<Address> unity(Integer code, int type) {
if (type == 1 && code == null) {
code = 86;
}
//sql语句:select * from address where address_type = #{type} and parent = #{code}
return new LambdaQueryChainWrapper<>(this.addressService.getBaseMapper()).eq(Address::getAddressType, type)
.eq(Address::getParent, code)
.list();
}
注:①. 需要改为你自己的查询方法,即查询出address表的所有数据。all()方法执行结果见下方。
处理结果示例
[
{
"parent": 86,
"address": "北京市",
"code": 110000,
"junior": [
{
"parent": 110000,
"address": "东城区",
"code": 110101
},
...
]
},
{
"parent": 86,
"address": "河北省",
"code": 130000,
"junior": [
{
"parent": 130000,
"address": "石家庄市",
"code": 130100,
"junior": [
{
"parent": 130100,
"address": "长安区",
"code": 130102
},
...
]
},
...
]
},
...
]
后续
- 查询数据和数据的处理消耗资源较高,需做缓存处理(地址数据很少变动,缓存过期时间可设置的长一点)。
- 目前数据库数据只涉及到省、市、区,可继续向下扩展。