新增 支持达梦数据库

新增 Sequences 增加 updateTime
新增 增加查询序号是否锁定的方法 locked
新增 增加将序号设为未使用的方法 unused
新增 增加 SequencesUnlock find(SequencesUnlock sequencesUnlock) 和 SequencesUnused find(SequencesUnused sequencesUnused)
This commit is contained in:
2025-01-15 11:42:46 +08:00
parent 670cd52c40
commit e2e5939810
18 changed files with 282 additions and 41 deletions

View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.yanghuanglin</groupId> <groupId>com.yanghuanglin</groupId>
<artifactId>seq</artifactId> <artifactId>seq</artifactId>
<version>1.10.0</version> <version>1.11.0</version>
<name>seq</name> <name>seq</name>
<description>seq</description> <description>seq</description>
<properties> <properties>

View File

@@ -32,6 +32,11 @@ public class TableConfig {
*/ */
private String createTimeColumn = "create_time"; private String createTimeColumn = "create_time";
/**
* 序号表中最后使用时间
*/
private String updateTimeColumn = "update_time";
public String getTable() { public String getTable() {
return table; return table;
} }
@@ -71,4 +76,12 @@ public class TableConfig {
public void setCreateTimeColumn(String createTimeColumn) { public void setCreateTimeColumn(String createTimeColumn) {
this.createTimeColumn = createTimeColumn.toLowerCase(); this.createTimeColumn = createTimeColumn.toLowerCase();
} }
public String getUpdateTimeColumn() {
return updateTimeColumn;
}
public void setUpdateTimeColumn(String updateTimeColumn) {
this.updateTimeColumn = updateTimeColumn;
}
} }

View File

@@ -10,6 +10,11 @@ import java.util.List;
* @since 2022/1/28 * @since 2022/1/28
*/ */
public interface SequencesUnlockDao { public interface SequencesUnlockDao {
/**
* 查找某个未被锁定的序号
*/
SequencesUnlock find(SequencesUnlock sequencesUnlock);
/** /**
* 保存使用中的序号 * 保存使用中的序号
*/ */

View File

@@ -11,6 +11,11 @@ import java.util.List;
*/ */
public interface SequencesUnusedDao { public interface SequencesUnusedDao {
/**
* 查找某个未被使用的序号
*/
SequencesUnused find(SequencesUnused sequencesUnused);
/** /**
* 根据keytype查找seq最小的空闲序号 * 根据keytype查找seq最小的空闲序号
*/ */

View File

@@ -49,6 +49,7 @@ public abstract class SequencesBase {
sql = sql.replaceAll("`seq`", String.format("`%s`", tableConfig.getSeqColumn())); sql = sql.replaceAll("`seq`", String.format("`%s`", tableConfig.getSeqColumn()));
sql = sql.replaceAll("`create_time`", String.format("`%s`", tableConfig.getCreateTimeColumn())); sql = sql.replaceAll("`create_time`", String.format("`%s`", tableConfig.getCreateTimeColumn()));
break; break;
case Dameng:
case PostgreSQL: case PostgreSQL:
case KingbaseES: case KingbaseES:
sql = sql.replaceAll("\"sequences(_unused|_unlock)\"", String.format("%s$1", tableConfig.getTable())); sql = sql.replaceAll("\"sequences(_unused|_unlock)\"", String.format("%s$1", tableConfig.getTable()));
@@ -72,11 +73,12 @@ public abstract class SequencesBase {
* @param sqlString sql语句 * @param sqlString sql语句
* @return 处理后的语句 * @return 处理后的语句
*/ */
protected String adapter(String sqlString) { protected String dbAdapter(String sqlString) {
switch (dbType) { switch (dbType) {
case MySQL: case MySQL:
break; break;
case PostgreSQL: case PostgreSQL:
case Dameng:
case KingbaseES: case KingbaseES:
sqlString = sqlString.replaceAll("`(.+?)`", "\"$1\""); sqlString = sqlString.replaceAll("`(.+?)`", "\"$1\"");
break; break;

View File

@@ -12,7 +12,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
* @author yanghuanglin * @author yanghuanglin
* @since 2022/1/28 * @since 2022/1/28
*/ */
@SuppressWarnings("SqlResolve") @SuppressWarnings({"SqlResolve", "SqlSourceToSinkFlow"})
public class SequencesDaoImpl extends SequencesBase implements SequencesDao { public class SequencesDaoImpl extends SequencesBase implements SequencesDao {
public SequencesDaoImpl(JdbcTemplate jdbcTemplate, TableConfig tableConfig, DbType dbType) { public SequencesDaoImpl(JdbcTemplate jdbcTemplate, TableConfig tableConfig, DbType dbType) {
@@ -24,11 +24,12 @@ public class SequencesDaoImpl extends SequencesBase implements SequencesDao {
String sql = "select * from `%s` where `%s`=? and `%s`=?"; String sql = "select * from `%s` where `%s`=? and `%s`=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn());
try { try {
return this.jdbcTemplate.queryForObject(adapter(sql), (rs, rowNum) -> { return this.jdbcTemplate.queryForObject(dbAdapter(sql), (rs, rowNum) -> {
Sequences result = new Sequences(); Sequences result = new Sequences();
result.setKey(rs.getString(tableConfig.getKeyColumn())); result.setKey(rs.getString(tableConfig.getKeyColumn()));
result.setType(rs.getString(tableConfig.getTypeColumn())); result.setType(rs.getString(tableConfig.getTypeColumn()));
result.setSeq(rs.getLong(tableConfig.getSeqColumn())); result.setSeq(rs.getLong(tableConfig.getSeqColumn()));
result.setUpdateTime(rs.getDate(tableConfig.getUpdateTimeColumn()));
return result; return result;
}, sequences.getKey(), sequences.getType()); }, sequences.getKey(), sequences.getType());
} catch (EmptyResultDataAccessException ignored) { } catch (EmptyResultDataAccessException ignored) {
@@ -40,7 +41,7 @@ public class SequencesDaoImpl extends SequencesBase implements SequencesDao {
public boolean save(Sequences sequences) { public boolean save(Sequences sequences) {
String sql = "insert into `%s`(`%s`,`%s`,`%s`) values(?,?,?)"; String sql = "insert into `%s`(`%s`,`%s`,`%s`) values(?,?,?)";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn());
int result = this.jdbcTemplate.update(adapter(sql), sequences.getKey(), sequences.getType(), sequences.getSeq()); int result = this.jdbcTemplate.update(dbAdapter(sql), sequences.getKey(), sequences.getType(), sequences.getSeq());
return result != 0; return result != 0;
} }
@@ -48,7 +49,7 @@ public class SequencesDaoImpl extends SequencesBase implements SequencesDao {
public boolean update(Sequences sequences) { public boolean update(Sequences sequences) {
String sql = "update `%s` set `%s`=? where `%s`=? and `%s`=?"; String sql = "update `%s` set `%s`=? where `%s`=? and `%s`=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getSeqColumn(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getSeqColumn(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn());
int result = this.jdbcTemplate.update(adapter(sql), sequences.getSeq(), sequences.getKey(), sequences.getType()); int result = this.jdbcTemplate.update(dbAdapter(sql), sequences.getSeq(), sequences.getKey(), sequences.getType());
return result != 0; return result != 0;
} }

View File

@@ -4,6 +4,7 @@ import com.yanghuanglin.seq.config.TableConfig;
import com.yanghuanglin.seq.dao.SequencesUnlockDao; import com.yanghuanglin.seq.dao.SequencesUnlockDao;
import com.yanghuanglin.seq.enums.DbType; import com.yanghuanglin.seq.enums.DbType;
import com.yanghuanglin.seq.po.SequencesUnlock; import com.yanghuanglin.seq.po.SequencesUnlock;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
@@ -14,18 +15,36 @@ import java.util.List;
* @author yanghuanglin * @author yanghuanglin
* @since 2022/1/28 * @since 2022/1/28
*/ */
@SuppressWarnings("SqlResolve") @SuppressWarnings({"SqlResolve", "SqlSourceToSinkFlow"})
public class SequencesUnlockDaoImpl extends SequencesBase implements SequencesUnlockDao { public class SequencesUnlockDaoImpl extends SequencesBase implements SequencesUnlockDao {
public SequencesUnlockDaoImpl(JdbcTemplate jdbcTemplate, TableConfig tableConfig, DbType dbType) { public SequencesUnlockDaoImpl(JdbcTemplate jdbcTemplate, TableConfig tableConfig, DbType dbType) {
super(jdbcTemplate, tableConfig, dbType); super(jdbcTemplate, tableConfig, dbType);
} }
@Override
public SequencesUnlock find(SequencesUnlock sequencesUnlock) {
String sql = "select * from `%s_unlock` where `%s`=? and `%s`=? and `%s`=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn());
try {
return this.jdbcTemplate.queryForObject(dbAdapter(sql), (rs, rowNum) -> {
SequencesUnlock result = new SequencesUnlock();
result.setKey(rs.getString(tableConfig.getKeyColumn()));
result.setType(rs.getString(tableConfig.getTypeColumn()));
result.setSeq(rs.getLong(tableConfig.getSeqColumn()));
result.setCreateTime(rs.getDate(tableConfig.getCreateTimeColumn()));
return result;
}, sequencesUnlock.getKey(), sequencesUnlock.getType(), sequencesUnlock.getSeq());
} catch (EmptyResultDataAccessException ignored) {
return null;
}
}
@Override @Override
public boolean save(SequencesUnlock sequencesUnlock) { public boolean save(SequencesUnlock sequencesUnlock) {
String sql = "insert into `%s_unlock`(`%s`,`%s`,`%s`,`%s`) values(?,?,?,?)"; String sql = "insert into `%s_unlock`(`%s`,`%s`,`%s`,`%s`) values(?,?,?,?)";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn(), tableConfig.getCreateTimeColumn());
int result = this.jdbcTemplate.update(adapter(sql), sequencesUnlock.getKey(), sequencesUnlock.getType(), sequencesUnlock.getSeq(), sequencesUnlock.getCreateTime()); int result = this.jdbcTemplate.update(dbAdapter(sql), sequencesUnlock.getKey(), sequencesUnlock.getType(), sequencesUnlock.getSeq(), sequencesUnlock.getCreateTime());
return result != 0; return result != 0;
} }
@@ -36,9 +55,9 @@ public class SequencesUnlockDaoImpl extends SequencesBase implements SequencesUn
if (sequencesUnlock.getSeq() != null) { if (sequencesUnlock.getSeq() != null) {
sql += " and `%s`=?"; sql += " and `%s`=?";
sql = String.format(sql, tableConfig.getSeqColumn()); sql = String.format(sql, tableConfig.getSeqColumn());
return this.jdbcTemplate.update(adapter(sql), sequencesUnlock.getKey(), sequencesUnlock.getType(), sequencesUnlock.getSeq()) != 0; return this.jdbcTemplate.update(dbAdapter(sql), sequencesUnlock.getKey(), sequencesUnlock.getType(), sequencesUnlock.getSeq()) != 0;
} else { } else {
return this.jdbcTemplate.update(adapter(sql), sequencesUnlock.getKey(), sequencesUnlock.getType()) != 0; return this.jdbcTemplate.update(dbAdapter(sql), sequencesUnlock.getKey(), sequencesUnlock.getType()) != 0;
} }
} }
@@ -46,7 +65,7 @@ public class SequencesUnlockDaoImpl extends SequencesBase implements SequencesUn
public List<SequencesUnlock> listAll() { public List<SequencesUnlock> listAll() {
String sql = "select * from `%s_unlock`"; String sql = "select * from `%s_unlock`";
sql = String.format(sql, tableConfig.getTable()); sql = String.format(sql, tableConfig.getTable());
return this.jdbcTemplate.query(adapter(sql), rowMapper()); return this.jdbcTemplate.query(dbAdapter(sql), rowMapper());
} }
@Override @Override
@@ -55,15 +74,15 @@ public class SequencesUnlockDaoImpl extends SequencesBase implements SequencesUn
if (begin != null && end != null) { if (begin != null && end != null) {
sql = "select * from `%s_unlock` where `%s`>=? and `%s`<=?"; sql = "select * from `%s_unlock` where `%s`>=? and `%s`<=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.query(adapter(sql), rowMapper(), begin, end); return this.jdbcTemplate.query(dbAdapter(sql), rowMapper(), begin, end);
} else if (begin != null) { } else if (begin != null) {
sql = "select * from `%s_unlock` where `%s`>=?"; sql = "select * from `%s_unlock` where `%s`>=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.query(adapter(sql), rowMapper(), begin); return this.jdbcTemplate.query(dbAdapter(sql), rowMapper(), begin);
} else if (end != null) { } else if (end != null) {
sql = "select * from `%s_unlock` where `%s`<=?"; sql = "select * from `%s_unlock` where `%s`<=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.query(adapter(sql), rowMapper(), end); return this.jdbcTemplate.query(dbAdapter(sql), rowMapper(), end);
} else { } else {
return listAll(); return listAll();
} }
@@ -73,7 +92,7 @@ public class SequencesUnlockDaoImpl extends SequencesBase implements SequencesUn
public boolean deleteAll() { public boolean deleteAll() {
String sql = "delete from `%s_unlock`"; String sql = "delete from `%s_unlock`";
sql = String.format(sql, tableConfig.getTable()); sql = String.format(sql, tableConfig.getTable());
int result = this.jdbcTemplate.update(adapter(sql)); int result = this.jdbcTemplate.update(dbAdapter(sql));
return result != 0; return result != 0;
} }
@@ -83,15 +102,15 @@ public class SequencesUnlockDaoImpl extends SequencesBase implements SequencesUn
if (begin != null && end != null) { if (begin != null && end != null) {
sql = "delete from `%s_unlock` where `%s`>=? and `%s`<=?"; sql = "delete from `%s_unlock` where `%s`>=? and `%s`<=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.update(adapter(sql), begin, end) != 0; return this.jdbcTemplate.update(dbAdapter(sql), begin, end) != 0;
} else if (begin != null) { } else if (begin != null) {
sql = "delete from `%s_unlock` where `%s`>=?"; sql = "delete from `%s_unlock` where `%s`>=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.update(adapter(sql), begin) != 0; return this.jdbcTemplate.update(dbAdapter(sql), begin) != 0;
} else if (end != null) { } else if (end != null) {
sql = "delete from `%s_unlock` where `%s`<=?"; sql = "delete from `%s_unlock` where `%s`<=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.update(adapter(sql), end) != 0; return this.jdbcTemplate.update(dbAdapter(sql), end) != 0;
} else { } else {
return deleteAll(); return deleteAll();
} }

View File

@@ -19,19 +19,37 @@ import java.util.List;
* @author yanghuanglin * @author yanghuanglin
* @since 2022/1/28 * @since 2022/1/28
*/ */
@SuppressWarnings("SqlResolve") @SuppressWarnings({"SqlResolve", "SqlSourceToSinkFlow"})
public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUnusedDao { public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUnusedDao {
public SequencesUnusedDaoImpl(JdbcTemplate jdbcTemplate, TableConfig tableConfig, DbType dbType) { public SequencesUnusedDaoImpl(JdbcTemplate jdbcTemplate, TableConfig tableConfig, DbType dbType) {
super(jdbcTemplate, tableConfig, dbType); super(jdbcTemplate, tableConfig, dbType);
} }
@Override
public SequencesUnused find(SequencesUnused sequencesUnused) {
String sql = "select * from `%s_unused` where `%s`=? and `%s`=? and `%s`=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn());
try {
return this.jdbcTemplate.queryForObject(dbAdapter(sql), (rs, rowNum) -> {
SequencesUnused result = new SequencesUnused();
result.setKey(rs.getString(tableConfig.getKeyColumn()));
result.setType(rs.getString(tableConfig.getTypeColumn()));
result.setSeq(rs.getLong(tableConfig.getSeqColumn()));
result.setCreateTime(rs.getDate(tableConfig.getCreateTimeColumn()));
return result;
}, sequencesUnused.getKey(), sequencesUnused.getType(), sequencesUnused.getSeq());
} catch (EmptyResultDataAccessException ignored) {
return null;
}
}
@Override @Override
public SequencesUnused findMinSeq(SequencesUnused sequencesUnused) { public SequencesUnused findMinSeq(SequencesUnused sequencesUnused) {
String sql = "select * from `%s_unused` where `%s`=? and `%s`=? order by `%s` asc limit 0,1"; String sql = "select * from `%s_unused` where `%s`=? and `%s`=? order by `%s` asc limit 0,1";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn());
try { try {
return this.jdbcTemplate.queryForObject(adapter(sql), rowMapper(), sequencesUnused.getKey(), sequencesUnused.getType()); return this.jdbcTemplate.queryForObject(dbAdapter(sql), rowMapper(), sequencesUnused.getKey(), sequencesUnused.getType());
} catch (EmptyResultDataAccessException ignored) { } catch (EmptyResultDataAccessException ignored) {
return null; return null;
} }
@@ -42,7 +60,7 @@ public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUn
try { try {
String sql = "select * from `%s_unused` where `%s`=? and `%s`=? order by `%s` desc limit 0,1"; String sql = "select * from `%s_unused` where `%s`=? and `%s`=? order by `%s` desc limit 0,1";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn());
return this.jdbcTemplate.queryForObject(adapter(sql), rowMapper(), sequencesUnused.getKey(), sequencesUnused.getType()); return this.jdbcTemplate.queryForObject(dbAdapter(sql), rowMapper(), sequencesUnused.getKey(), sequencesUnused.getType());
} catch (EmptyResultDataAccessException ignored) { } catch (EmptyResultDataAccessException ignored) {
return null; return null;
} }
@@ -52,7 +70,7 @@ public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUn
public boolean delete(SequencesUnused sequencesUnused) { public boolean delete(SequencesUnused sequencesUnused) {
String sql = "delete from `%s_unused` where `%s`=? and `%s`=? and `%s`=?"; String sql = "delete from `%s_unused` where `%s`=? and `%s`=? and `%s`=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn());
int result = this.jdbcTemplate.update(adapter(sql), sequencesUnused.getKey(), sequencesUnused.getType(), sequencesUnused.getSeq()); int result = this.jdbcTemplate.update(dbAdapter(sql), sequencesUnused.getKey(), sequencesUnused.getType(), sequencesUnused.getSeq());
return result != 0; return result != 0;
} }
@@ -60,7 +78,7 @@ public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUn
public boolean save(SequencesUnused sequencesUnused) { public boolean save(SequencesUnused sequencesUnused) {
String sql = "insert into `%s_unused`(`%s`,`%s`,`%s`,`%s`) values(?,?,?,?)"; String sql = "insert into `%s_unused`(`%s`,`%s`,`%s`,`%s`) values(?,?,?,?)";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn(), tableConfig.getCreateTimeColumn());
int result = this.jdbcTemplate.update(adapter(sql), sequencesUnused.getKey(), sequencesUnused.getType(), sequencesUnused.getSeq(), sequencesUnused.getCreateTime()); int result = this.jdbcTemplate.update(dbAdapter(sql), sequencesUnused.getKey(), sequencesUnused.getType(), sequencesUnused.getSeq(), sequencesUnused.getCreateTime());
return result != 0; return result != 0;
} }
@@ -68,7 +86,7 @@ public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUn
public boolean saveBatch(List<SequencesUnused> sequencesUnusedList) { public boolean saveBatch(List<SequencesUnused> sequencesUnusedList) {
String sql = "insert into `%s_unused`(`%s`,`%s`,`%s`,`%s`) values(?,?,?,?)"; String sql = "insert into `%s_unused`(`%s`,`%s`,`%s`,`%s`) values(?,?,?,?)";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getKeyColumn(), tableConfig.getTypeColumn(), tableConfig.getSeqColumn(), tableConfig.getCreateTimeColumn());
int[] result = this.jdbcTemplate.batchUpdate(adapter(sql), new BatchPreparedStatementSetter() { int[] result = this.jdbcTemplate.batchUpdate(dbAdapter(sql), new BatchPreparedStatementSetter() {
@Override @Override
public void setValues(PreparedStatement ps, int i) throws SQLException { public void setValues(PreparedStatement ps, int i) throws SQLException {
SequencesUnused sequencesUnused = sequencesUnusedList.get(i); SequencesUnused sequencesUnused = sequencesUnusedList.get(i);
@@ -95,7 +113,7 @@ public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUn
public boolean deleteAll() { public boolean deleteAll() {
String sql = "delete from `%s_unused`"; String sql = "delete from `%s_unused`";
sql = String.format(sql, tableConfig.getTable()); sql = String.format(sql, tableConfig.getTable());
int result = this.jdbcTemplate.update(adapter(sql)); int result = this.jdbcTemplate.update(dbAdapter(sql));
return result != 0; return result != 0;
} }
@@ -105,15 +123,15 @@ public class SequencesUnusedDaoImpl extends SequencesBase implements SequencesUn
if (begin != null && end != null) { if (begin != null && end != null) {
sql = "delete from `%s_unused` where `%s`>=? and `%s`<=?"; sql = "delete from `%s_unused` where `%s`>=? and `%s`<=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.update(adapter(sql), begin, end) != 0; return this.jdbcTemplate.update(dbAdapter(sql), begin, end) != 0;
} else if (begin != null) { } else if (begin != null) {
sql = "delete from `%s_unused` where `%s`>=?"; sql = "delete from `%s_unused` where `%s`>=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.update(adapter(sql), begin) != 0; return this.jdbcTemplate.update(dbAdapter(sql), begin) != 0;
} else if (end != null) { } else if (end != null) {
sql = "delete from `%s_unused` where `%s`<=?"; sql = "delete from `%s_unused` where `%s`<=?";
sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn()); sql = String.format(sql, tableConfig.getTable(), tableConfig.getCreateTimeColumn());
return this.jdbcTemplate.update(adapter(sql), end) != 0; return this.jdbcTemplate.update(dbAdapter(sql), end) != 0;
} else { } else {
return deleteAll(); return deleteAll();
} }

View File

@@ -3,6 +3,8 @@ package com.yanghuanglin.seq.enums;
public enum DbType { public enum DbType {
//MySQL数据库 //MySQL数据库
MySQL("mysql"), MySQL("mysql"),
//达梦数据库
Dameng("dm"),
//人大金仓数据库 //人大金仓数据库
KingbaseES("pgsql"), KingbaseES("pgsql"),
//PostgreSQL数据库 //PostgreSQL数据库

View File

@@ -221,6 +221,14 @@ public interface Generator {
*/ */
Sequences parse(String formatted, String pattern, Integer fixLength); Sequences parse(String formatted, String pattern, Integer fixLength);
/**
* 查询序号是否已被锁定
*
* @param sequences 需要查询的序号
* @return 锁定结果
*/
boolean locked(Sequences sequences);
/** /**
* 锁定指定序号,在序号生成后,调用该序号的逻辑完成后需要执行此方法 * 锁定指定序号,在序号生成后,调用该序号的逻辑完成后需要执行此方法
* <p/> * <p/>
@@ -244,6 +252,14 @@ public interface Generator {
*/ */
boolean lock(Sequences sequences, boolean ignoreSeq); boolean lock(Sequences sequences, boolean ignoreSeq);
/**
* 将序号设为未使用
*
* @param sequences 需要设为未使用的序号
* @return 设置结果
*/
boolean unused(Sequences sequences);
/** /**
* 释放所有未使用的序号 * 释放所有未使用的序号
* <p/> * <p/>

View File

@@ -22,6 +22,7 @@ import java.util.regex.Pattern;
import static com.yanghuanglin.seq.enums.FormatPlaceholder.*; import static com.yanghuanglin.seq.enums.FormatPlaceholder.*;
@SuppressWarnings("CallToPrintStackTrace")
public class SequencesGenerator implements Generator { public class SequencesGenerator implements Generator {
private final TransactionTemplate transactionTemplate; private final TransactionTemplate transactionTemplate;
private final SequencesDao sequencesDao; private final SequencesDao sequencesDao;
@@ -89,7 +90,11 @@ public class SequencesGenerator implements Generator {
//根据传入的key和type新生成查询条件对象 //根据传入的key和type新生成查询条件对象
Sequences condition = new Sequences(key, type); Sequences condition = new Sequences(key, type);
if (!withOutSeq) { if (Boolean.TRUE.equals(withOutSeq)) {
//不包含序号
condition.setWithOutSeq(true);
return condition;
} else {
//不是不包含序号的序号对象(有可能格式中只配置了#year##month##day#,序号就不用自增,也不用入库,直接返回即可) //不是不包含序号的序号对象(有可能格式中只配置了#year##month##day#,序号就不用自增,也不用入库,直接返回即可)
//找到正在使用的最大序号 //找到正在使用的最大序号
Sequences sequences = sequencesDao.find(condition); Sequences sequences = sequencesDao.find(condition);
@@ -123,9 +128,6 @@ public class SequencesGenerator implements Generator {
} }
sequences.setWithOutSeq(false); sequences.setWithOutSeq(false);
return result ? sequences : null; return result ? sequences : null;
} else {
condition.setWithOutSeq(true);
return condition;
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -305,10 +307,30 @@ public class SequencesGenerator implements Generator {
} }
@Override @Override
public synchronized boolean lock(Sequences sequences) { public boolean locked(Sequences sequences) {
if (sequences == null || sequences.getWithOutSeq()) if (sequences == null || Boolean.TRUE.equals(sequences.getWithOutSeq()))
return true; return true;
SequencesUnlock condition = new SequencesUnlock(sequences); SequencesUnlock condition = new SequencesUnlock(sequences);
//将使用中表的对应数据删除,空闲表中数据在生成时会删除,因此这里不需要处理该表
return Boolean.TRUE.equals(transactionTemplate.execute(status -> {
try {
SequencesUnlock sequencesUnlock = sequencesUnlockDao.find(condition);
return sequencesUnlock == null;
} catch (Exception e) {
e.printStackTrace();
status.setRollbackOnly();
return false;
}
}));
}
@Override
public synchronized boolean lock(Sequences sequences) {
if (sequences == null || Boolean.TRUE.equals(sequences.getWithOutSeq()))
return true;
SequencesUnlock condition = new SequencesUnlock(sequences);
//将使用中表的对应数据删除,空闲表中数据在生成时会删除,因此这里不需要处理该表 //将使用中表的对应数据删除,空闲表中数据在生成时会删除,因此这里不需要处理该表
return Boolean.TRUE.equals(transactionTemplate.execute(status -> { return Boolean.TRUE.equals(transactionTemplate.execute(status -> {
try { try {
@@ -325,7 +347,7 @@ public class SequencesGenerator implements Generator {
public synchronized boolean lock(Sequences sequences, boolean ignoreSeq) { public synchronized boolean lock(Sequences sequences, boolean ignoreSeq) {
if (!ignoreSeq) if (!ignoreSeq)
return lock(sequences); return lock(sequences);
if (sequences == null || sequences.getWithOutSeq()) if (sequences == null || Boolean.TRUE.equals(sequences.getWithOutSeq()))
return true; return true;
SequencesUnlock condition = new SequencesUnlock(sequences); SequencesUnlock condition = new SequencesUnlock(sequences);
condition.setSeq(null); condition.setSeq(null);
@@ -341,6 +363,24 @@ public class SequencesGenerator implements Generator {
})); }));
} }
@Override
public boolean unused(Sequences sequences) {
if (sequences == null)
return true;
SequencesUnused condition = new SequencesUnused(sequences);
condition.setCreateTime(new Date());
//在未使用中表增加需要设为未使用的序号
return Boolean.TRUE.equals(transactionTemplate.execute(status -> {
try {
return sequencesUnusedDao.save(condition);
} catch (Exception e) {
e.printStackTrace();
status.setRollbackOnly();
return false;
}
}));
}
@Override @Override
public synchronized boolean release() { public synchronized boolean release() {
//列出所有使用中表存在的序号 //列出所有使用中表存在的序号

View File

@@ -2,6 +2,8 @@ package com.yanghuanglin.seq.po;
import com.yanghuanglin.seq.config.BaseConfig; import com.yanghuanglin.seq.config.BaseConfig;
import java.util.Date;
/** /**
* 当前序号 * 当前序号
* *
@@ -24,6 +26,11 @@ public class Sequences {
*/ */
protected Long seq = 0L; protected Long seq = 0L;
/**
* 最后使用时间
*/
private Date updateTime;
/** /**
* 临时字段序号对应的年份如2022年如果能获取到的话 * 临时字段序号对应的年份如2022年如果能获取到的话
* 该字段仅用于解析序号字符串时解析出对应年份用于合成key序号对应的key为SNT+年份,返回的为其年份) * 该字段仅用于解析序号字符串时解析出对应年份用于合成key序号对应的key为SNT+年份,返回的为其年份)
@@ -101,6 +108,14 @@ public class Sequences {
this.seq = seq; this.seq = seq;
} }
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Integer getYear() { public Integer getYear() {
return year; return year;
} }
@@ -180,10 +195,11 @@ public class Sequences {
"key='" + key + '\'' + "key='" + key + '\'' +
", type='" + type + '\'' + ", type='" + type + '\'' +
", seq=" + seq + ", seq=" + seq +
", updateTime=" + updateTime +
", year=" + year + ", year=" + year +
", month=" + month + ", month=" + month +
", day=" + day + ", day=" + day +
", fix=" + fix + ", fix='" + fix + '\'' +
", withOutSeq=" + withOutSeq + ", withOutSeq=" + withOutSeq +
'}'; '}';
} }

View File

@@ -0,0 +1,26 @@
CREATE TABLE IF NOT EXISTS "sequences"
(
"key" VARCHAR(64) NOT NULL,
"type" VARCHAR(64) NOT NULL,
"seq" BIGINT NOT NULL,
"update_time" TIMESTAMP,
PRIMARY KEY ("key", "type")
);
COMMENT ON TABLE "sequences" IS '当前序号表';
COMMENT ON COLUMN "sequences"."key" IS '序号英文名称';
COMMENT ON COLUMN "sequences"."type" IS '序号类型';
COMMENT ON COLUMN "sequences"."seq" IS '已使用到的序号';
COMMENT ON COLUMN "sequences"."update_time" IS '最后使用时间';
/*
@触发器设置,功能:自动记录更新时间
@触发器名为 SEQUENCES_UPDATE_TIME
@触发器执行范围为每行生效
*/
CREATE OR REPLACE TRIGGER SEQUENCES_UPDATE_TIME BEFORE UPDATE ON "sequences" FOR EACH ROW
BEGIN
NEW."update_time":=SYSDATE;
END;
/*启动触发器*/
ALTER TRIGGER SEQUENCES_UPDATE_TIME ENABLE;

View File

@@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS "sequences_unlock"
(
"key" VARCHAR(64) NOT NULL,
"type" VARCHAR(64) NOT NULL,
"seq" BIGINT NOT NULL,
"create_time" TIMESTAMP NOT NULL,
PRIMARY KEY ("key", "type", "seq")
);
COMMENT ON TABLE "sequences_unlock" IS '未锁定序号表';
COMMENT ON COLUMN "sequences_unlock"."key" IS '序号英文名称';
COMMENT ON COLUMN "sequences_unlock"."type" IS '序号类型';
COMMENT ON COLUMN "sequences_unlock"."seq" IS '尚未锁定的序号';
COMMENT ON COLUMN "sequences_unlock"."create_time" IS '使用时间';

View File

@@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS "sequences_unused"
(
"key" VARCHAR(64) NOT NULL,
"type" VARCHAR(64) NOT NULL,
"seq" BIGINT NOT NULL,
"create_time" TIMESTAMP NOT NULL,
PRIMARY KEY ("key", "type", "seq")
);
COMMENT ON TABLE "sequences_unused" IS '闲置序号表';
COMMENT ON COLUMN "sequences_unused"."key" IS '序号英文名称';
COMMENT ON COLUMN "sequences_unused"."type" IS '序号类型';
COMMENT ON COLUMN "sequences_unused"."seq" IS '闲置的的序号';
COMMENT ON COLUMN "sequences_unused"."create_time" IS '设为闲置序号的时间';

View File

@@ -3,5 +3,6 @@ CREATE TABLE IF NOT EXISTS `sequences`
`key` VARCHAR(64) NOT NULL COMMENT '序号英文名称', `key` VARCHAR(64) NOT NULL COMMENT '序号英文名称',
`type` VARCHAR(64) NOT NULL COMMENT '序号类型', `type` VARCHAR(64) NOT NULL COMMENT '序号类型',
`seq` BIGINT(20) NOT NULL COMMENT '已使用到的序号', `seq` BIGINT(20) NOT NULL COMMENT '已使用到的序号',
`update_time` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '最后使用时间',
PRIMARY KEY (`key`, `type`) PRIMARY KEY (`key`, `type`)
) COMMENT '当前序号表'; ) COMMENT '当前序号表';

View File

@@ -3,9 +3,30 @@ CREATE TABLE IF NOT EXISTS "sequences"
"key" VARCHAR(64) NOT NULL, "key" VARCHAR(64) NOT NULL,
"type" VARCHAR(64) NOT NULL, "type" VARCHAR(64) NOT NULL,
"seq" INT8 NOT NULL, "seq" INT8 NOT NULL,
"update_time" TIMESTAMP,
PRIMARY KEY ("key", "type") PRIMARY KEY ("key", "type")
); );
COMMENT ON TABLE "sequences" IS '当前序号表'; COMMENT ON TABLE "sequences" IS '当前序号表';
COMMENT ON COLUMN "sequences"."key" IS '序号英文名称'; COMMENT ON COLUMN "sequences"."key" IS '序号英文名称';
COMMENT ON COLUMN "sequences"."type" IS '序号类型'; COMMENT ON COLUMN "sequences"."type" IS '序号类型';
COMMENT ON COLUMN "sequences"."seq" IS '已使用到的序号'; COMMENT ON COLUMN "sequences"."seq" IS '已使用到的序号';
COMMENT ON COLUMN "sequences"."update_time" IS '最后使用时间';
/*
触发器函数用户更新update_time字段
*/
CREATE OR REPLACE FUNCTION SEQUENCES_UPDATE_TIME() RETURNS TRIGGER AS $$
BEGIN
NEW."update_time" := current_timestamp;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
/*
@触发器设置,功能:自动记录更新时间
@触发器名为 SEQUENCES_UPDATE_TIME
@触发器执行范围为每行生效
*/
DROP TRIGGER IF EXISTS SEQUENCES_UPDATE_TIME ON "sequences" CASCADE;
CREATE TRIGGER SEQUENCES_UPDATE_TIME BEFORE UPDATE ON "sequences" FOR EACH ROW EXECUTE FUNCTION SEQUENCES_UPDATE_TIME();

View File

@@ -24,7 +24,7 @@ public class SeqTest {
private static final Generator generator; private static final Generator generator;
static { static {
dataSource = pgsql(); dataSource = mysql();
GeneratorConfig generatorConfig = new GeneratorConfig(dataSource); GeneratorConfig generatorConfig = new GeneratorConfig(dataSource);
System.out.println("DbType: " + generatorConfig.getDbType()); System.out.println("DbType: " + generatorConfig.getDbType());
@@ -124,4 +124,34 @@ public class SeqTest {
sequences.setType("MISSION"); sequences.setType("MISSION");
System.out.println(sequences); System.out.println(sequences);
} }
@Test
public void unusedTest() {
Sequences sequences = new Sequences();
sequences.setKey("0010001$distrainCode2024");
sequences.setType("MISSION");
sequences.setSeq(1L);
boolean result = generator.unused(sequences);
assert result;
}
@Test
public void lockTest() {
Sequences sequences = new Sequences();
sequences.setKey("0010001$distrainCode2024");
sequences.setType("MISSION");
sequences.setSeq(1L);
boolean result = generator.lock(sequences);
assert result;
}
@Test
public void lockedTest() {
Sequences sequences = new Sequences();
sequences.setKey("0010001$distrainCode2024");
sequences.setType("MISSION");
sequences.setSeq(1L);
boolean result = generator.locked(sequences);
System.out.println("locked: " + result);
}
} }