All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.neko233.skilltree.game.redDot.impl.RedDotTreeByMysql Maven / Gradle / Ivy
package com.neko233.skilltree.game.redDot.impl;
import com.neko233.skilltree.commons.core.utils.*;
import com.neko233.skilltree.commons.sql.SqlTemplate233;
import com.neko233.skilltree.game.redDot.RedDotTree;
import com.neko233.skilltree.game.redDot.dto.RedDotDto;
import com.neko233.skilltree.game.redDot.dto.RedPointRemoveResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 红点树 by mysql
*/
@Slf4j
public class RedDotTreeByMysql implements RedDotTree {
public static final String CREATE_TABLE_IF_NOT_EXISTS =
"create table if not exists red_point_tree " +
" ( " +
" id bigint primary key auto_increment, " +
" userId varchar(128) comment '用户id', " +
" path varchar(512) comment '路径. 根节点为 /', " +
" count long comment '数量', " +
" expireMs bigint comment '过期毫秒时间戳', " +
" createDt datetime default now() comment '创建时间', " +
" unique key uk_user_redPoint(userId, path) " +
" );" ;
public static final String UPSERT_SQL = StringUtils233.trimIdent("insert into red_point_tree(userId, path, count, expireMs) " +
" Values (${userId}, ${path}, ${count}, ${expireMs}) " +
" on duplicate key update count = values(count), expireMs = values(expireMs)"
);
// db
private final DataSource dataSource;
// 直接接入
private final RedDotTreeByMemory redDotTreeByMemory;
// 用户 id
private final String userId;
public static RedDotTreeByMysql create(Number userId, DataSource dataSource) {
if (userId == null) {
throw new IllegalArgumentException("userId can not null!");
}
return create(String.valueOf(userId), dataSource);
}
public static RedDotTreeByMysql create(String userId, DataSource dataSource) {
if (StringUtils.isBlank(userId)) {
throw new IllegalArgumentException("userId can not blank ! ");
}
return new RedDotTreeByMysql(userId, dataSource);
}
private RedDotTreeByMysql(String userId, DataSource dataSource) {
this.dataSource = dataSource;
this.userId = userId;
try (Connection c = dataSource.getConnection()) {
PreparedStatement ps = c.prepareStatement(CREATE_TABLE_IF_NOT_EXISTS);
ps.executeUpdate();
} catch (Exception e) {
log.error("[RedPo] create table error! create SQL = {}", CREATE_TABLE_IF_NOT_EXISTS, e);
// create table error
}
String selectSql = KvTemplate233.builder("Select * From red_point_tree Where userId = ${userId}")
.put("userId", String.valueOf(userId))
.build();
try (Connection c = dataSource.getConnection();
PreparedStatement ps = c.prepareStatement(selectSql)) {
ResultSet rs = ps.executeQuery();
LinkedList redDotDtoList = new LinkedList<>();
while (rs.next()) {
redDotDtoList.add(RedDotDto.createByDbQuery(rs));
}
this.redDotTreeByMemory = RedDotTreeByMemory.from(redDotDtoList);
} catch (Exception e) {
throw new RuntimeException("init error", e);
} finally {
}
}
/**
* Insert, Update, Delete
*/
@Override
public void flush(List toUpdatePathList) {
List redPointList = null;
if (CollectionUtils233.isEmpty(toUpdatePathList)) {
redPointList = this.getAllRedDotList();
} else {
redPointList = toUpdatePathList.stream()
.map(redDotTreeByMemory::getRedDot)
.collect(Collectors.toList());
}
try (Connection c = dataSource.getConnection()) {
// delete
if (CollectionUtils.isEmpty(redPointList)) {
this.deleteAllMyData(c);
return;
}
// upsert
upsert(redPointList, c);
} catch (Exception e) {
throw new RuntimeException("[RedDotTree] 红点 upsert error", e);
}
}
private void deleteAllMyData(Connection c) throws SQLException {
String deleteSql = SqlTemplate233.builder("Delete From red_point_tree Where userId = ${userId} ")
.put("userId", userId)
.build();
PreparedStatement ps = c.prepareStatement(deleteSql);
log.debug("userId = {} clear all redPoint Data. Delete SQL = {}", userId, deleteSql);
ps.execute();
}
private void upsert(List redPointList, Connection c) throws SQLException {
List uspertSqlList = redPointList.stream()
.map(data -> SqlTemplate233.builder(UPSERT_SQL)
.put("userId", userId)
.put("path", data.getPath())
.put("count", data.getCount())
.put("expireMs", data.getExpireMs())
.build())
.collect(Collectors.toList());
// 挺搞的
PreparedStatement ps = null;
for (String sql : uspertSqlList) {
log.debug("[RedDotTree] upsert 红点. sql = {}", sql);
ps = c.prepareStatement(sql);
ps.execute();
}
CloseableUtils233.close(ps);
}
@Override
public void clear() {
this.redDotTreeByMemory.clear();
flush();
}
@Nullable
@Override
public Long getExpireMsByPath(String path) {
return this.redDotTreeByMemory.getExpireMsByPath(path);
}
@Override
@Nullable
public RedDotDto getByRefresh(String path) {
RedDotDto byRefresh = this.redDotTreeByMemory.getByRefresh(path);
if (byRefresh == null) {
flush(ListUtils233.of(path));
}
return byRefresh;
}
@Override
public List getAllChildPathList(String path) {
return this.redDotTreeByMemory.getAllChildPathList(path);
}
@Override
public List getAllParentPathList(String path) {
return this.redDotTreeByMemory.getAllParentPathList(path);
}
@Override
public boolean isExpire(String path) {
return this.redDotTreeByMemory.isExpire(path);
}
@Override
public Map getPathToValueMap() {
return this.redDotTreeByMemory.getPathToValueMap();
}
@Override
@Nullable
public RedPointRemoveResult removeRedDot(String path) {
RedPointRemoveResult result = this.redDotTreeByMemory.removeRedDot(path);
if (result == null) {
return null;
}
List toRemovePathList = result.getRemoveChildPathList();
this.deleteMysqlDataByPath(toRemovePathList);
return result;
}
/**
* 删除 mysql 数据
*
* @param toRemovePathList 要移除的路径
*/
private void deleteMysqlDataByPath(List toRemovePathList) {
List deleteSqlList = toRemovePathList.stream()
.map(path -> SqlTemplate233.builder("Delete From red_point_tree Where userId = ${userId} and path = ${path} ")
.put("userId", userId)
.put("path", path)
.build())
.collect(Collectors.toList());
try (Connection c = dataSource.getConnection()) {
for (String s : deleteSqlList) {
PreparedStatement ps = c.prepareStatement(s);
ps.execute();
}
} catch (Exception e) {
throw new RuntimeException("delete error", e);
}
}
@Override
public List addRedDot(String path, int value, long expireTimeMs) {
List toUpdatePathList = this.redDotTreeByMemory.addRedDot(path, value, expireTimeMs);
flush(toUpdatePathList);
return toUpdatePathList;
}
@Override
public List updateRedDotValue(String path, long value) {
List toUpdatePathList = this.redDotTreeByMemory.updateRedDotValue(path, value);
flush(toUpdatePathList);
return toUpdatePathList;
}
@Override
public Map getAllDataMap(Collection filterPathList) {
return this.redDotTreeByMemory.getAllDataMap(filterPathList);
}
@Override
public Map getAllDataMap() {
return this.redDotTreeByMemory.getAllDataMap();
}
@Override
public RedDotDto getRedDot(String path) {
return this.redDotTreeByMemory.getRedDot(path);
}
@Override
public long getRedDotValue(String path) {
return this.redDotTreeByMemory.getRedDotValue(path);
}
@Override
public List getAllRedDotList() {
return this.redDotTreeByMemory.getAllRedDotList();
}
}