1 + 1 = 小可爱
package com.gs.game.annotations;
import java.lang.annotation.*;
/**
* 若世有神明 亦要胜他半子
*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FileSql {
String sql() default "";
String[] param() default {};
String[] join() default {};
String alias() default "";
String reverse() default "";
}
2 + 2 = 小可爱
package com.gs.game.controller.base;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.enums.IEnum;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gs.game.annotations.FileSql;
import com.gs.game.common.ResponseWrapper;
import com.gs.game.utils.ApplicationContextUtil;
import com.gs.game.utils.ThreadLocalUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.data.web.PageableDefault;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
public class IController<T> {
@PutMapping(value = "/_insert")
private ResponseWrapper insert(@RequestBody T t){
return ResponseWrapper.ok(insertT(t));
}
@PutMapping(value = "/_save")
private ResponseWrapper save(@RequestBody T t){
if(0 == updateTById(t)){
insertT(t);
}
return ResponseWrapper.ok(true);
}
@PutMapping(value = "/_updateById")
private ResponseWrapper updateById(@RequestBody T t){
return ResponseWrapper.ok(updateTById(t));
}
@DeleteMapping(value = "/_deleteById")
private ResponseWrapper deleteById(@RequestBody T t){
return ResponseWrapper.ok(deleteTById(t));
}
@GetMapping(value = "/_findById")
private ResponseWrapper findById(@RequestParam Map<String,Object> map){
return ResponseWrapper.ok( findTById(map) );
}
@GetMapping(value = "/_findOne")
private ResponseWrapper findOne(@RequestParam Map<String,Object> map){
return ResponseWrapper.ok(findTOne(map));
}
@GetMapping(value = "/_find")
private ResponseWrapper find(@RequestParam Map<String,Object> map){
return ResponseWrapper.ok(findT(map));
}
@GetMapping(value = "/_page")
private ResponseWrapper page(@PageableDefault Page page, @RequestParam Map<String,Object> map){
return ResponseWrapper.ok(pageT(page,map));
}
private JdbcTemplate jdbcTemplate;
public JdbcTemplate getJdbcTemplate(){
if(null == jdbcTemplate){
jdbcTemplate = ApplicationContextUtil.getBean( JdbcTemplate.class );
}
return jdbcTemplate;
}
private Class<T> entityClass;
public Class<T> getEntityClass() {
if(null == entityClass){
entityClass = getSuperClassGenericType(getClass(), 0);
}
return entityClass;
}
public void setEntityClass(Class<T> entityClass) {
this.entityClass = entityClass;
}
public List<Field> fieldList;
public Map<String, List<Field>> findFieldMap(){
return findFileIds().stream().filter(f -> !ObjectUtils.isEmpty(f.getName())).collect(Collectors.groupingBy(g -> g.getName()));
}
public Field byName(String name){
List<Field> fields = findFieldMap().get(name);
if(!ObjectUtils.isEmpty(fields)){
return fields.get(0);
}
return null;
}
public List<Field> findFileIds() {
if(!ObjectUtils.isEmpty(fieldList)){
return fieldList;
}
Class<?> lass = getEntityClass();
List<Field> list = new ArrayList<>();
if(null != lass){
while (lass !=null && !lass.getName().equals("java.lang.Object")) {
Field[] fields = lass.getDeclaredFields();
for (Field field : fields) {
list.add(field);
}
lass = lass.getSuperclass();
}
}
return list.stream().filter(f -> !"serialVersionUID".equals(f.getName())).collect(Collectors.toList());
}
private String getTable(){
return (getEntityClass().getName().substring( getEntityClass().getName().lastIndexOf(".") + 1).substring(0, 1).toLowerCase() + getEntityClass().getName().substring( getEntityClass().getName().lastIndexOf(".") + 1).substring(1)).replaceAll("[A-Z]", "_$0").toLowerCase();
}
// 反射对象获取泛型
public static Class getSuperClassGenericType(final Class<?> clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
return Object.class;
}
if (!(params[index] instanceof Class)) {
return Object.class;
}
return (Class<?>) params[index];
}
// 基础方法
private T writedata(Map<String, Object> maps){
if(ObjectUtils.isEmpty(maps)){
return null;
}
List<T> writedata = writedata(new ArrayList() {{
add(maps);
}});
return writedata.get(0);
}
private List<T> writedata(List<Map<String, Object>> maps){
try {
if(ObjectUtils.isEmpty(maps)){
return new ArrayList<>();
}
List<T> resurtList = new ArrayList();
for (Map m : maps){
T t = getEntityClass().newInstance();
for(Field f : findFileIds()){
f.setAccessible(true);
Object value = m.get(f.getName());
if(null != value){
if(f.getType().isEnum()){
boolean isIEnum = false;
for (Class<?> inte : f.getType().getInterfaces()) {
if("com.baomidou.mybatisplus.core.enums.IEnum".equals( (inte.getTypeName() + "") )){
isIEnum = true;
}
}
if(isIEnum){
IEnum[] enumCons = (IEnum[]) f.getType().getEnumConstants();
for (IEnum an : enumCons){
if((value + "").equals( (an.getValue() + "") )){
value = an;
}
}
}
if(!isIEnum){
value = Enum.valueOf( ((Class) f.getType()), "" + value);
}
} else if("java.lang.Byte".equals(f.getType().getName())){
value = Byte.valueOf(value + "");
} else if("java.lang.Short".equals(f.getType().getName())){
value = Short.valueOf(value + "");
} else if("java.lang.Integer".equals(f.getType().getName())){
value = Integer.valueOf(value + "");
} else if("java.lang.Long".equals(f.getType().getName())){
value = Long.valueOf(value + "");
} else if("java.lang.Float".equals(f.getType().getName())){
value = Float.valueOf(value + "");
} else if("java.lang.Double".equals(f.getType().getName())){
value = Double.valueOf(value + "");
} else if("java.lang.Boolean".equals(f.getType().getName())){
value = Boolean.valueOf(value + "");
} else if("java.lang.String".equals(f.getType().getName())){
value = value + "";
} else if("java.time.Instant".equals(f.getType().getName())){
if(value instanceof java.sql.Timestamp){
value = ( (java.sql.Timestamp) value).toInstant() ;
}
if(value instanceof java.time.LocalDateTime){
value = ( (java.time.LocalDateTime ) value).atZone(java.time.ZoneId.systemDefault()).toInstant();
}
} else if("java.util.Date".equals(f.getType().getName())){
if(value instanceof java.sql.Timestamp){
value = new java.util.Date( ( (java.sql.Timestamp) value).getTime() ) ;
}
if(value instanceof java.time.LocalDateTime){
value = new java.util.Date( ( (java.time.LocalDateTime ) value).atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli() );
}
} else if("java.util.Map".equals(f.getType().getName())){
value = JSON.parseObject(value + "",Map.class);
} else if("java.util.HashMap".equals(f.getType().getName())){
value = JSON.parseObject(value + "",HashMap.class);
}
f.set(t,value);
}
}
resurtList.add(t);
}
return resurtList;
}catch (Exception e){
throw new RuntimeException(e);
}
}
private T insertT(T t){
try {
Field f = byName("id");
f.setAccessible(true);
if(ObjectUtils.isEmpty(f.get(t))){
Object id = nextId();
if("java.lang.Integer".equals(f.getType().getName())){
id = Integer.valueOf(id + "");
} else if("java.lang.Long".equals(f.getType().getName())){
id = Long.valueOf(id + "");
} else if("java.lang.String".equals(f.getType().getName())){
id = id + "";
}
f.set(t,id);
}
getJdbcTemplate().update(insertSql(t));
/*
KeyHolder keyHolder = new GeneratedKeyHolder();
getJdbcTemplate().update(conn -> conn.prepareStatement(insertSql(t), Statement.RETURN_GENERATED_KEYS), keyHolder);
Number key = keyHolder.getKey();
*/
return t;
}catch (Exception e){
throw new RuntimeException(e);
}
}
private String deleteSql(Map<String,Object> map){
try {
String sql = "DELETE FROM `"+getTable()+"` WHERE 1 = 1 " + whereSql(process(map)) + " ";
System.out.println(sql);
return sql;
}catch (Exception e){
throw new RuntimeException(e);
}
}
public int updateTById(T t){
try {
Field idField = byName("id");
idField.setAccessible(true);
Object id = idField.get(t);
if(ObjectUtils.isEmpty(id)){
return 0;
}
return getJdbcTemplate().update(updateSql(t,new HashMap(){{
put("id",id);
}}));
}catch (Exception e){
return 0;
}
}
public T findTById(Map<String,Object> map){
if(ObjectUtils.isEmpty(map)){
return null;
}
if(ObjectUtils.isEmpty(map.get("id"))){
return null;
}
return writedata(getJdbcTemplate().queryForMap(selectSql(new HashMap() {{
put("id", map.get("id"));
}})));
}
public T findTOne(Map<String,Object> map){
return writedata(getJdbcTemplate().queryForMap(selectSql(map)));
}
public List<T> findT(Map<String,Object> map){
return writedata(getJdbcTemplate().queryForList(selectSql(map)));
}
public Page pageT(Page page, Map<String,Object> map){
String sql = selectSql(map);
long current = page.getCurrent();
if(current <= 0){
current = 1;
}
long finalC = current;
return new Page(){{
setRecords(writedata(getJdbcTemplate().queryForList("select * from ( " + sql + ") limitcount limit " + ((finalC - 1) * page.getSize()) + "," + (finalC * page.getSize()))));
setTotal(getJdbcTemplate().queryForObject("select count(*) as count from ( " + sql + ") limitcount", Integer.class));
setSize(page.getSize());
setCurrent(finalC);
}};
}
// Sql 语句处理
private String insertSql(T t){
try {
String sql = "INSERT INTO `"+getTable()+"` ";
String fieldStr = " ( ";
String valueStr = " ( ";
for (int i = 0; i < findFileIds().size(); i++) {
Field f = findFileIds().get(i);
f.setAccessible(true);
// 默认值处理
if(ObjectUtils.isEmpty(f.get(t))){
if("createdBy".equals(f.getName())){
f.set(t,ThreadLocalUtil.getUserId());
}
if("createdDate".equals(f.getName())){
f.set(t,java.time.Instant.now());
}
}
Object value = f.get(t);
if(!ObjectUtils.isEmpty(value)){
TableField tableField = f.getAnnotation(TableField.class);
//字段上没有注解 FileSql 和 TableField 注解 或者 有TableField注解但 exist 为 TRUE 是数据库字段
if( (null == f.getAnnotation(FileSql.class)) && (null == tableField ? true : (tableField.exist()) )){
for (Class<?> inte : f.getType().getInterfaces()) {
if("com.baomidou.mybatisplus.core.enums.IEnum".equals( (inte.getTypeName() + "") )){
value = ((com.baomidou.mybatisplus.core.enums.IEnum) value).getValue();
}
}
if("java.time.Instant".equals(f.getType().getName())) {
value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date.from( ((java.time.Instant)value) )) ;
}
fieldStr = fieldStr + "`" + f.getName().replaceAll("[A-Z]", "_$0").toLowerCase() + "`,";
valueStr = valueStr + "'" + value + "',";
}
}
}
// 去最后的逗号
if(-1 != fieldStr.lastIndexOf(",")){
fieldStr = fieldStr.substring(0,fieldStr.lastIndexOf(","))+fieldStr.substring(fieldStr.lastIndexOf(",")+1);
}
if(-1 != valueStr.lastIndexOf(",")){
valueStr = valueStr.substring(0,valueStr.lastIndexOf(","))+valueStr.substring(valueStr.lastIndexOf(",")+1);
}
fieldStr = fieldStr + " ) ";
valueStr = valueStr + " ) ";
sql = sql + fieldStr + " VALUES " + valueStr;
System.out.println(sql);
return sql;
}catch (Exception e){
throw new RuntimeException(e);
}
}
public int deleteTById(T t){
try {
if(ObjectUtils.isEmpty(t)){
return 0;
}
Field field = byName("id");
field.setAccessible(true);
if(ObjectUtils.isEmpty(field)){
return 0;
}
Object id = field.get(t);
if(ObjectUtils.isEmpty(id)){
return 0;
}
return getJdbcTemplate().update(deleteSql(new HashMap(){{
put("id",id);
}}));
}catch (Exception e){
throw new RuntimeException(e);
}
}
private String updateSql(T t, Map<String,Object> map){
try {
String sql = "UPDATE `"+getTable()+"` SET ";
for (Field f : findFileIds()){
f.setAccessible(true);
// 默认值处理
if(ObjectUtils.isEmpty(f.get(t))){
if("lastModifiedBy".equals(f.getName())){
f.set(t,ThreadLocalUtil.getUserId());
}
if("lastModifiedDate".equals(f.getName())){
f.set(t,java.time.Instant.now());
}
}
Object value = f.get(t);
if(null != value){
TableField tableField = f.getAnnotation(TableField.class);
//字段上没有注解 FileSql 和 TableField 注解 或者 有TableField注解但 exist 为 TRUE 是数据库字段
if( (null == f.getAnnotation(FileSql.class)) && (null == tableField ? true : (tableField.exist()) )){
if("java.time.Instant".equals(f.getType().getName())) {
value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date.from( ((java.time.Instant)value) )) ;
}
for (Class<?> inte : f.getType().getInterfaces()) {
if("com.baomidou.mybatisplus.core.enums.IEnum".equals( (inte.getTypeName() + "") )){
value = ((com.baomidou.mybatisplus.core.enums.IEnum) value).getValue();
}
}
sql = sql + f.getName().replaceAll("[A-Z]", "_$0").toLowerCase() + "='" + value +"',";
}
}
}
if(-1 != sql.lastIndexOf(",")){
sql = sql.substring(0,sql.lastIndexOf(","))+sql.substring(sql.lastIndexOf(",")+1);
}
sql = sql + " WHERE 1 = 1 " + whereSql(process(map)) + " ";
System.out.println(sql);
return sql;
}catch (Exception e){
throw new RuntimeException(e);
}
}
private String selectSql(Map<String,Object> map){
// 查询字段返回 SQL
String fieldSql = "";
// LEFT JOIN SQL
String leftjoin = "";
for (int i = 0; i < findFileIds().size(); i++) {
Field f = findFileIds().get(i);
TableField tableField = f.getAnnotation(TableField.class);
FileSql annon = f.getAnnotation(FileSql.class);
String fileIdBy = "";
//字段上没有注解 FileSql 和 TableField 注解 或者 有TableField注解但 exist 为 TRUE 是数据库字段
if( (null == annon) && (null == tableField ? true : (tableField.exist()) )){
fileIdBy = (getTable() + "." + f.getName().replaceAll("[A-Z]", "_$0").toLowerCase()) + " as " + f.getName() + " ";
}
if( (null != annon)){
String reverse = f.getName();
if(!ObjectUtils.isEmpty(annon.reverse())){
reverse = annon.reverse();
}
String alias = f.getName();
if(!ObjectUtils.isEmpty(annon.alias())){
alias = annon.alias();
}
fileIdBy = (alias + "." + reverse.replaceAll("[A-Z]", "_$0").toLowerCase()) + " as " + f.getName() + " ";
if(!ObjectUtils.isEmpty(annon.sql())){
leftjoin = leftjoin + " LEFT JOIN ( " + annon.sql() + ") " + alias + " ON 1 = 1 ";
for (int j = 0; j < annon.param().length; j++) {
String param = annon.param()[j];
String join = annon.join()[j];
leftjoin = leftjoin + " AND " + getTable() + "." + param.replaceAll("[A-Z]", "_$0").toLowerCase() + " = " + alias + "." + join.replaceAll("[A-Z]", "_$0").toLowerCase() + " ";
}
}
}
if(!ObjectUtils.isEmpty(fileIdBy)){
if(i != (findFileIds().size() - 1)){
fieldSql = fieldSql + fileIdBy + ", ";
}
if(i == (findFileIds().size() - 1)){
fieldSql = fieldSql + fileIdBy + " ";
}
}
}
String sql = "SELECT "+ fieldSql +" FROM " + getTable() + leftjoin + " WHERE 1 = 1 " + whereSql(map) + " ";
// ORDER BY 处理
List<Map> orderList = new ArrayList();
map.keySet().forEach(f ->{
if(!ObjectUtils.isEmpty(map.get(f))){
for (int i = 0; i < map.keySet().size(); i++) {
Map<String,Object> order = new HashMap<>();
String orderKey = "orderBy["+i+"].";
if(f.startsWith((orderKey+"column"))){
order.put("column",map.get(f));
}
if(f.startsWith((orderKey+"asc"))){
order.put("asc",map.get(f));
}
Field field = byName((order.get("column") + ""));
if (!ObjectUtils.isEmpty(field)) {
TableField tableField = field.getAnnotation(TableField.class);
if( !(!ObjectUtils.isEmpty(tableField) && !tableField.exist() && null == field.getAnnotation(FileSql.class)) ){
orderList.add( order );
}
}
}
}
});
if(!ObjectUtils.isEmpty(orderList)){
String orderBy = " order by ";
for (int i = 0; i < orderList.size(); i++) {
Map<String,Object> f = orderList.get(i);
Field field = byName((f.get("column") + ""));
if (!ObjectUtils.isEmpty(field)) {
String column = (f.get("column")+"").replaceAll("[A-Z]", "_$0").toLowerCase();
FileSql annon = field.getAnnotation(FileSql.class);
String tableCopy = getTable();
if(null != annon){
tableCopy = annon.alias();
if(ObjectUtils.isEmpty(tableCopy)){
tableCopy = field.getName();
}
String reverse = annon.reverse();
if(ObjectUtils.isEmpty(reverse)){
reverse = field.getName();
}
column = reverse.replaceAll("[A-Z]", "_$0").toLowerCase();
}
String type = "desc";
if("true".equals(f.get("asc") + "" )){
type = "asc";
}
if(i != (orderList.size() - 1)){
orderBy = orderBy + tableCopy + "." + column + " " + type + " , ";
}
if(i == (orderList.size() - 1)){
orderBy = orderBy + tableCopy + "." + column + " " + type + " ";
}
}
}
sql = sql + orderBy;
}
if(ObjectUtils.isEmpty(orderList)){
//排序默认处理
Field createdDate = byName("createdDate");
if(!ObjectUtils.isEmpty(createdDate)){
FileSql annon = createdDate.getAnnotation(FileSql.class);
if(ObjectUtils.isEmpty(annon)){
sql = sql + " order by " + getTable() + "." +"createdDate".replaceAll("[A-Z]", "_$0").toLowerCase() + " " + "desc" + " ";
}
}
}
System.out.println(sql);
return sql;
}
// 只保留 单表字段
private Map<String,Object> process(Map<String,Object> request){
Map<String,Object> map = new HashMap<>();
for (String f : request.keySet()){
Field field = byName(f);
if(!ObjectUtils.isEmpty(field)){
TableField tableField = field.getAnnotation(TableField.class);
if( !(!ObjectUtils.isEmpty(tableField) && !tableField.exist() && null == field.getAnnotation(FileSql.class)) ){
map.put(f,request.get(f));
}
}
}
return map;
}
private String whereSql(Map<String,Object> request){
// 空值去除
Map<String,Object> map = new HashMap<>();
for (String f : request.keySet()){
if(!ObjectUtils.isEmpty(request.get(f))){
map.put(f,request.get(f));
}
}
String sql = "";
List<Map> paramList = new ArrayList();
// WHERE 遍历参数 参数处理
map.keySet().forEach(f -> {
paramList.add(new HashMap() {{
put("type", "eq");
put("column", f);
put("value", map.get(f));
}});
/**
* 特殊字段处理
*/
//ge_data
if(f.endsWith(("GeData"))){
paramList.add(new HashMap(){{
put("type","ge");
put("column",f.substring(0,f.length()-6));
put("value",map.get(f));
}});
}
//le_data
if(f.endsWith(("LeData"))){
paramList.add(new HashMap(){{
put("type","le");
put("column",f.substring(0,f.length()-6));
put("value",map.get(f));
}});
}
//gt_data
if(f.endsWith(("GtData"))){
paramList.add(new HashMap(){{
put("type","gt");
put("column",f.substring(0,f.length()-6));
put("value",map.get(f));
}});
}
//lt_data
if(f.endsWith(("LtData"))){
paramList.add(new HashMap(){{
put("type","lt");
put("column",f.substring(0,f.length()-6));
put("value",map.get(f));
}});
}
// like_data
if(f.endsWith(("LikeData"))){
paramList.add(new HashMap(){{
put("type","like");
put("column",f.substring(0,f.length()-8));
put("value",map.get(f));
}});
}
// like_data
if(f.endsWith(("NeData"))){
paramList.add(new HashMap(){{
put("type","ne");
put("column",f.substring(0,f.length()-6));
put("value",map.get(f));
}});
}
//个性化字段处理
for (int i = 0; i < map.keySet().size(); i++) {
Map<String,Object> param = new HashMap<>();
String parmKey = "["+i+"].";
if(f.startsWith((parmKey+"type"))){
param.put("type",map.get(f));
}
if(f.startsWith((parmKey+"column"))){
param.put("column",map.get(f));
}
if(f.startsWith((parmKey+"value"))){
param.put("value",map.get(f));
}
if(3 == param.keySet().size()){
paramList.add(param);
}
}
});
if(!ObjectUtils.isEmpty(paramList)){
for(Map<String,Object> paramMap : paramList){
Field field = byName((paramMap.get("column") + ""));
if(!ObjectUtils.isEmpty(field)){
String column = (paramMap.get("column")+"").replaceAll("[A-Z]", "_$0").toLowerCase();
FileSql annon = field.getAnnotation(FileSql.class);
String tableCopy = getTable();
if(null != annon){
tableCopy = field.getName();
if(!ObjectUtils.isEmpty(annon.alias())){
tableCopy = annon.alias();
}
String reverse = field.getName();
if(!ObjectUtils.isEmpty(annon.reverse())){
reverse = annon.reverse();
}
column = reverse.replaceAll("[A-Z]", "_$0").toLowerCase();
}
switch ( (paramMap.get("type") + "") ){
case "eq":
sql = sql + " AND " + tableCopy + "." + column + " = '" + (paramMap.get("value")) + "' ";
break;
case "ne":
sql = sql + " AND " + tableCopy + "." + column + " != '" + (paramMap.get("value")) + "' ";
break;
case "like":
sql = sql + " AND " + tableCopy + "." + column + " like '%" + (paramMap.get("value")) + "%' ";
break;
case "leftlike":
sql = sql + " AND " + tableCopy + "." + column + " like '%" + (paramMap.get("value")) + "' ";
break;
case "rightlike":
sql = sql + " AND " + tableCopy + "." + column + " like '" + (paramMap.get("value")) + "%' ";
break;
case "notlike":
sql = sql + " AND " + tableCopy + "." + column + " not like '%" + (paramMap.get("value")) + "%' ";
break;
case "gt":
sql = sql + " AND " + tableCopy + "." + column + " > '" + (paramMap.get("value")) + "' ";
break;
case "lt":
sql = sql + " AND " + tableCopy + "." + column + " < '" + (paramMap.get("value")) + "' ";
break;
case "ge":
sql = sql + " AND " + tableCopy + "." + column + " >= '" + (paramMap.get("value")) + "' ";
break;
case "le":
sql = sql + " AND " + tableCopy + "." + column + " <= '" + (paramMap.get("value")) + "' ";
break;
case "in":
sql = sql + " AND " + tableCopy + "." + column + " in ( ";
List value = (List) paramMap.get("value");
for (int i = 0; i < value.size(); i++) {
if(i != (value.size() - 1)){
sql = sql + value.get(i) + ", ";
}
if(i == (value.size() - 1)){
sql = sql + value.get(i) + " ";
}
}
sql = sql + ") ";
break;
}
}
}
}
return sql;
}
/**
*
* 雪花算法
*
*/
// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
private final static long twepoch = 1288834974657L;
// 机器标识位数
private final static long workerIdBits = 5L;
// 数据中心标识位数
private final static long datacenterIdBits = 5L;
// 机器ID最大值
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
// 数据中心ID最大值
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// 毫秒内自增位
private final static long sequenceBits = 12L;
// 机器ID偏左移12位
private final static long workerIdShift = sequenceBits;
// 数据中心ID左移17位
private final static long datacenterIdShift = sequenceBits + workerIdBits;
// 时间毫秒左移22位
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
/* 上次生产id时间戳 */
private static long lastTimestamp = -1L;
// 0,并发控制
private long sequence = 0L;
private final long workerId;
// 数据标识id部分
private final long datacenterId;
public IController(){
this.datacenterId = getDatacenterId(maxDatacenterId);
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
public IController(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;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
StringBuffer mpid = new StringBuffer();
mpid.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (!name.isEmpty()) {
/*
* GET jvmPid
*/
mpid.append(name.split("@")[0]);
}
/*
* MAC + PID 的 hashcode 获取16个低位
*/
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}
protected static long getDatacenterId(long maxDatacenterId) {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
id = ((0x000000FF & (long) mac[mac.length - 1])
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
} catch (Exception e) {
System.out.println(" getDatacenterId: " + e.getMessage());
}
return id;
}
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
// 当前毫秒内,则+1
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 当前毫秒内计数满了,则等待下一秒
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
// ID偏移组合生成最终的ID,并返回ID
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift) | sequence;
return nextId;
}
}