sql
CREATE TABLE `pc_mdc_address` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`pid` bigint(50) NOT NULL COMMENT '父ID',
`city_code` varchar(50) DEFAULT '' COMMENT '城市編碼',
`ad_code` varchar(50) DEFAULT '' COMMENT '區域編碼',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '地址名稱',
`level` tinyint(1) NOT NULL COMMENT '級別(省市區縣)',
`polyline` varchar(255) DEFAULT '' COMMENT '行政區邊界座標點',
`center` varchar(255) DEFAULT '' COMMENT '城市中心點',
PRIMARY KEY (`id`),
KEY `I_PARENT_ID` (`pid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=367047247247843329 DEFAULT CHARSET=utf8;
測試類
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = Application.class)
public class AddressTest {
@Resource
private PcMdcAddressMapper pcMdcAddressMapper;
public String getCityData() throws IOException {
String result = null;
HttpPost httpPost = new HttpPost("http://restapi.amap.com/v3/config/district");
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("key", "3c831a5f6d3fbf3820e067f7********"));
nvps.add(new BasicNameValuePair("keywords", null));
nvps.add(new BasicNameValuePair("subdistrict", "3"));
nvps.add(new BasicNameValuePair("extensions", "base"));
CloseableHttpClient client = HttpClients.createDefault();
httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
CloseableHttpResponse response = client.execute(httpPost);
//獲取結果實體
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定編碼轉換結果實體爲String類型
result = EntityUtils.toString(entity, "utf-8");
}
return result;
}
@Test
public void saveAddress() throws IOException {
String json = getCityData();
Result result = JSON.parseObject(json, Result.class);
System.out.println(result);
List<Districts> districts = result.getDistricts();
// 生成城市數據
for (Districts district : districts) {
buildAddressData(district, 0L);
}
}
final SnowflakeIdWorker idg = new SnowflakeIdWorker(2, 31);
private void buildAddressData(Districts district, Long pid) {
PcMdcAddress address = new PcMdcAddress();
BeanUtils.copyProperties(district, address, "level");
address.setAdCode(district.getAdcode());
address.setCityCode(district.getCitycode());
String level = district.getLevel();
if ("country".equals(level)) {
address.setLevel(0);
} else if ("province".equals(level)) {
address.setLevel(1);
} else if ("city".equals(level)) {
address.setLevel(2);
} else if ("district".equals(level)) {
address.setLevel(3);
} else if ("street".equals(level)) {
address.setLevel(4);
} else {
throw new RuntimeException("數據異常");
}
long id = idg.nextId();
address.setId(id);
address.setPid(pid);
pcMdcAddressMapper.insert(address);
System.out.println(district.getCitycode() + "," + district.getName());
List<Districts> districts1 = district.getDistricts();
for (Districts districts2 : districts1) {
buildAddressData(districts2, id);
}
}
數據實體類
@Data
public class Districts {
private String citycode;
private String adcode;
private String name;
private String polyline;
private String center;
private String level;
/**
* The Districts.
*/
List<Districts> districts;
}
@Data
public class Result {
private String status;
private String info;
private String infocode;
private String count;
private Suggestion suggestion;
private List<Districts> districts;
}
@Data
public class Suggestion {
private String[] keywords;
private String[] cities;
}
雪花算法
package tk.mybatis.springboot.util;
/**
* The class Snowflake id worker.
* Created by [email protected]
*/
public class SnowflakeIdWorker {
// ==============================Fields===========================================
/**
* 開始時間截 (2015-01-01)
*/
private final long twepoch = 1420041600000L;
/**
* 機器id所佔的位數
*/
private final long workerIdBits = 5L;
/**
* 數據標識id所佔的位數
*/
private final long datacenterIdBits = 5L;
/**
* 支持的最大機器id, 結果是31 (這個移位算法可以很快的計算出幾位二進制數所能表示的最大十進制數)
*/
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
/**
* 支持的最大數據標識id, 結果是31
*/
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/**
* 序列在id中佔的位數
*/
private final long sequenceBits = 12L;
/**
* 機器ID向左移12位
*/
private final long workerIdShift = sequenceBits;
/**
* 數據標識id向左移17位(12+5)
*/
private final long datacenterIdShift = sequenceBits + workerIdBits;
/**
* 時間截向左移22位(5+5+12)
*/
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
/**
* 生成序列的掩碼, 這裏爲4095 (0b111111111111=0xfff=4095)
*/
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
/**
* 工作機器ID(0~31)
*/
private long workerId;
/**
* 數據中心ID(0~31)
*/
private long datacenterId;
/**
* 毫秒內序列(0~4095)
*/
private long sequence = 0L;
/**
* 上次生成ID的時間截
*/
private long lastTimestamp = -1L;
//==============================Constructors=====================================
/**
* 構造函數
*
* @param workerId 工作ID (0~31)
* @param datacenterId 數據中心ID (0~31)
*/
public SnowflakeIdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
// ==============================Methods==========================================
/**
* 獲得下一個ID (該方法是線程安全的)
*
* @return SnowflakeId long
*/
public synchronized long nextId() {
long timestamp = timeGen();
//如果當前時間小於上一次ID生成的時間戳, 說明系統時鐘回退過這個時候應當拋出異常
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
//如果是同一時間生成的, 則進行毫秒內序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//毫秒內序列溢出
if (sequence == 0) {
//阻塞到下一個毫秒,獲得新的時間戳
timestamp = tilNextMillis(lastTimestamp);
}
}
//時間戳改變, 毫秒內序列重置
else {
sequence = 0L;
}
//上次生成ID的時間截
lastTimestamp = timestamp;
//移位並通過或運算拼到一起組成64位的ID
return ((timestamp - twepoch) << timestampLeftShift) //
| (datacenterId << datacenterIdShift) //
| (workerId << workerIdShift) //
| sequence;
}
/**
* 阻塞到下一個毫秒, 直到獲得新的時間戳
*
* @param lastTimestamp 上次生成ID的時間截
*
* @return 當前時間戳
*/
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
/**
* 返回以毫秒爲單位的當前時間
*
* @return 當前時間(毫秒)
*/
private long timeGen() {
return System.currentTimeMillis();
}
}
數據庫對應實體
@Data
@Table(name = "pc_mdc_address")
public class PcMdcAddress {
/**
* ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 地址名稱
*/
private String name;
/**
* 父ID
*/
private Long pid;
/**
* 城市編碼
*/
@Column(name = "city_code")
private String cityCode;
/**
* 級別(省市區縣)
*/
private Integer level;
/**
* 區域編碼
*/
@Column(name = "ad_code")
private String adCode;
/**
* 行政區邊界座標點
*/
private String polyline;
/**
* 城市中心點
*/
private String center;
}
Mapper
public interface StudentMapper extends MyMapper<Student> {
}
Mapper.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="tk.mybatis.springboot.mapper.PcMdcAddressMapper" >
<resultMap id="BaseResultMap" type="tk.mybatis.springboot.model.PcMdcAddress" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="BIGINT" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="pid" property="pid" jdbcType="BIGINT" />
<result column="city_code" property="cityCode" jdbcType="VARCHAR" />
<result column="level" property="level" jdbcType="INTEGER" />
<result column="ad_code" property="adCode" jdbcType="VARCHAR" />
<result column="polyline" property="polyline" jdbcType="VARCHAR" />
<result column="center" property="center" jdbcType="VARCHAR" />
</resultMap>
</mapper>
update pc_mdc_address set city_code='' where city_code='[]';
留個草稿, 以備不時之需, 代碼有點小問題 就是一個空數組的問題