Merge branch 'dev' of http://zhouxy.xyz:3000/ZhouXY108/plusone-commons into dev
commit
b1804a5005
12
pom.xml
12
pom.xml
|
@ -69,12 +69,24 @@
|
||||||
<groupId>com.zaxxer</groupId>
|
<groupId>com.zaxxer</groupId>
|
||||||
<artifactId>HikariCP</artifactId>
|
<artifactId>HikariCP</artifactId>
|
||||||
<version>4.0.3</version>
|
<version>4.0.3</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.postgresql</groupId>
|
<groupId>org.postgresql</groupId>
|
||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<version>42.3.8</version>
|
<version>42.3.8</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
<artifactId>checker-qual</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ public final class MapWrapper<K, V> extends AbstractMapWrapper<K, V, MapWrapper<
|
||||||
return new Builder<>(new HashMap<>(initialCapacity, loadFactor));
|
return new Builder<>(new HashMap<>(initialCapacity, loadFactor));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <K, V> Builder<K, V> wrapTreeMap() {
|
public static <K extends Comparable<? super K>, V> Builder<K, V> wrapTreeMap() {
|
||||||
return new Builder<>(new TreeMap<>());
|
return new Builder<>(new TreeMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,9 @@ public class Predicates {
|
||||||
* .and(StringUtils::isNotEmpty);
|
* .and(StringUtils::isNotEmpty);
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param <T> 目标类型
|
||||||
* @param predicate
|
* @param predicate 原 {@link Predicate} 实例
|
||||||
* @return
|
* @return 包装的 {@link Predicate} 实例
|
||||||
*/
|
*/
|
||||||
public static <T> Predicate<T> of(Predicate<? super T> predicate) {
|
public static <T> Predicate<T> of(Predicate<? super T> predicate) {
|
||||||
return predicate::test;
|
return predicate::test;
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class DbRecord extends AbstractMapWrapper<String, Object, DbRecord> {
|
||||||
public <T> Set<T> getValueAsSet(String key) {
|
public <T> Set<T> getValueAsSet(String key) {
|
||||||
return this.<Collection<T>>getAndConvert(key)
|
return this.<Collection<T>>getAndConvert(key)
|
||||||
.map(l -> (l instanceof Set) ? (Set<T>) l : new HashSet<>(l))
|
.map(l -> (l instanceof Set) ? (Set<T>) l : new HashSet<>(l))
|
||||||
.orElse(Collections.<T>emptySet());
|
.orElse(Collections.emptySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public OptionalInt getValueAsInt(String key) {
|
public OptionalInt getValueAsInt(String key) {
|
||||||
|
|
|
@ -24,5 +24,5 @@ import com.google.common.annotations.Beta;
|
||||||
@Beta
|
@Beta
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ResultMap<T> {
|
public interface ResultMap<T> {
|
||||||
T map(ResultSet rs) throws SQLException;
|
T map(ResultSet rs, int rowNumber) throws SQLException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,8 +100,9 @@ public class SimpleJdbcTemplate {
|
||||||
}
|
}
|
||||||
try (ResultSet rs = stmt.executeQuery()) {
|
try (ResultSet rs = stmt.executeQuery()) {
|
||||||
List<T> result = new ArrayList<>();
|
List<T> result = new ArrayList<>();
|
||||||
|
int rowNumber = 0;
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
T e = resultMap.map(rs);
|
T e = resultMap.map(rs, rowNumber++);
|
||||||
result.add(e);
|
result.add(e);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -114,7 +115,7 @@ public class SimpleJdbcTemplate {
|
||||||
return (list.isEmpty()) ? Optional.empty() : Optional.ofNullable(list.get(0));
|
return (list.isEmpty()) ? Optional.empty() : Optional.ofNullable(list.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final ResultMap<Map<String, Object>> mapResultMap = rs -> {
|
public static final ResultMap<Map<String, Object>> mapResultMap = (rs, rowNumber) -> {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
ResultSetMetaData metaData = rs.getMetaData();
|
ResultSetMetaData metaData = rs.getMetaData();
|
||||||
int columnCount = metaData.getColumnCount();
|
int columnCount = metaData.getColumnCount();
|
||||||
|
@ -133,7 +134,7 @@ public class SimpleJdbcTemplate {
|
||||||
return queryFirst(sql, params, mapResultMap);
|
return queryFirst(sql, params, mapResultMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final ResultMap<DbRecord> recordResultMap = rs -> {
|
public static final ResultMap<DbRecord> recordResultMap = (rs, rowNumber) -> {
|
||||||
DbRecord result = new DbRecord();
|
DbRecord result = new DbRecord();
|
||||||
ResultSetMetaData metaData = rs.getMetaData();
|
ResultSetMetaData metaData = rs.getMetaData();
|
||||||
int columnCount = metaData.getColumnCount();
|
int columnCount = metaData.getColumnCount();
|
||||||
|
@ -153,26 +154,26 @@ public class SimpleJdbcTemplate {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<String> queryToString(String sql, Object... params) throws SQLException {
|
public Optional<String> queryToString(String sql, Object... params) throws SQLException {
|
||||||
return queryFirst(sql, params, (ResultSet rs) -> rs.getString(1));
|
return queryFirst(sql, params, (ResultSet rs, int rowNumber) -> rs.getString(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public OptionalInt queryToInt(String sql, Object... params) throws SQLException {
|
public OptionalInt queryToInt(String sql, Object... params) throws SQLException {
|
||||||
Optional<Integer> result = queryFirst(sql, params, (ResultSet rs) -> rs.getInt(1));
|
Optional<Integer> result = queryFirst(sql, params, (ResultSet rs, int rowNumber) -> rs.getInt(1));
|
||||||
return OptionalUtil.toOptionalInt(result);
|
return OptionalUtil.toOptionalInt(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OptionalLong queryToLong(String sql, Object... params) throws SQLException {
|
public OptionalLong queryToLong(String sql, Object... params) throws SQLException {
|
||||||
Optional<Long> result = queryFirst(sql, params, (ResultSet rs) -> rs.getLong(1));
|
Optional<Long> result = queryFirst(sql, params, (ResultSet rs, int rowNumber) -> rs.getLong(1));
|
||||||
return OptionalUtil.toOptionalLong(result);
|
return OptionalUtil.toOptionalLong(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OptionalDouble queryToDouble(String sql, Object... params) throws SQLException {
|
public OptionalDouble queryToDouble(String sql, Object... params) throws SQLException {
|
||||||
Optional<Double> result = queryFirst(sql, params, (ResultSet rs) -> rs.getDouble(1));
|
Optional<Double> result = queryFirst(sql, params, (ResultSet rs, int rowNumber) -> rs.getDouble(1));
|
||||||
return OptionalUtil.toOptionalDouble(result);
|
return OptionalUtil.toOptionalDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<BigDecimal> queryToBigDecimal(String sql, Object... params) throws SQLException {
|
public Optional<BigDecimal> queryToBigDecimal(String sql, Object... params) throws SQLException {
|
||||||
return queryFirst(sql, params, (ResultSet rs) -> rs.getBigDecimal(1));
|
return queryFirst(sql, params, (ResultSet rs, int rowNumber) -> rs.getBigDecimal(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int update(String sql, Object... params) throws SQLException {
|
public int update(String sql, Object... params) throws SQLException {
|
||||||
|
@ -224,7 +225,7 @@ public class SimpleJdbcTemplate {
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public static interface IAtom<T extends Exception> {
|
public interface IAtom<T extends Exception> {
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
void execute() throws SQLException, T;
|
void execute() throws SQLException, T;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,33 +9,22 @@ import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import xyz.zhouxy.plusone.commons.collection.SafeConcurrentHashMap;
|
||||||
|
|
||||||
import xyz.zhouxy.plusone.commons.collection.MapWrapper;
|
import xyz.zhouxy.plusone.commons.collection.MapWrapper;
|
||||||
|
|
||||||
public class DateTimeUtil {
|
public class DateTimeUtil {
|
||||||
|
|
||||||
private static final MapWrapper<String, DateTimeFormatter> DATE_TIME_FORMATTER_CHCHE = MapWrapper
|
private static final MapWrapper<String, DateTimeFormatter> DATE_TIME_FORMATTER_CACHE = MapWrapper
|
||||||
.<String, DateTimeFormatter>wrapHashMap()
|
.<String, DateTimeFormatter>wrap(new SafeConcurrentHashMap<>())
|
||||||
.keyChecker(StringUtils::isNotBlank)
|
.keyChecker(pattern -> Assert.isNotBlank(pattern, "The pattern could not be blank."))
|
||||||
.valueChecker(Objects::nonNull)
|
.valueChecker(formatter -> Assert.notNull(formatter, "The formatter could not be null."))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static DateTimeFormatter getDateTimeFormatter(String pattern) {
|
public static DateTimeFormatter getDateTimeFormatter(String pattern) {
|
||||||
if (!DATE_TIME_FORMATTER_CHCHE.containsKey(pattern)) {
|
return DATE_TIME_FORMATTER_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
|
||||||
synchronized (DateTimeUtil.class) {
|
|
||||||
if (!DATE_TIME_FORMATTER_CHCHE.containsKey(pattern)) {
|
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
|
||||||
DATE_TIME_FORMATTER_CHCHE.put(pattern, formatter);
|
|
||||||
return formatter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DATE_TIME_FORMATTER_CHCHE.get(pattern)
|
|
||||||
.orElseThrow(() -> new IllegalStateException("Formatter does not exist."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toString(String pattern, ZonedDateTime dateTime) {
|
public static String toString(String pattern, ZonedDateTime dateTime) {
|
||||||
|
@ -126,7 +115,7 @@ public class DateTimeUtil {
|
||||||
* 只是不同时区的表示。
|
* 只是不同时区的表示。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param dateTime {@link Date} 对象
|
* @param timeMillis 时间戳
|
||||||
* @param zone 时区
|
* @param zone 时区
|
||||||
* @return 带时区信息的地区时间
|
* @return 带时区信息的地区时间
|
||||||
*/
|
*/
|
||||||
|
@ -191,7 +180,7 @@ public class DateTimeUtil {
|
||||||
/**
|
/**
|
||||||
* 获取时间戳在指定时区的地区时间。
|
* 获取时间戳在指定时区的地区时间。
|
||||||
*
|
*
|
||||||
* @param dateTime {@link Date} 对象
|
* @param timeMillis 时间戳
|
||||||
* @param zone 时区
|
* @param zone 时区
|
||||||
* @return 地区时间
|
* @return 地区时间
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class MoreCollections {
|
||||||
return toConcurrentHashMap(c, keyGenerator, c.size());
|
return toConcurrentHashMap(c, keyGenerator, c.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <K, V> TreeMap<K, V> toTreeMap(Iterable<V> c, Function<? super V, K> keyGenerator) {
|
public static <K extends Comparable<? super K>, V> TreeMap<K, V> toTreeMap(Iterable<V> c, Function<? super V, K> keyGenerator) {
|
||||||
TreeMap<K, V> map = new TreeMap<>();
|
TreeMap<K, V> map = new TreeMap<>();
|
||||||
fillIntoEmptyMap(map, c, keyGenerator);
|
fillIntoEmptyMap(map, c, keyGenerator);
|
||||||
return map;
|
return map;
|
||||||
|
@ -106,7 +106,7 @@ public class MoreCollections {
|
||||||
return toConcurrentHashMap(c, keyGenerator, c.length);
|
return toConcurrentHashMap(c, keyGenerator, c.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <K, V> TreeMap<K, V> toTreeMap(V[] c, Function<? super V, K> keyGenerator) {
|
public static <K extends Comparable<? super K>, V> TreeMap<K, V> toTreeMap(V[] c, Function<? super V, K> keyGenerator) {
|
||||||
TreeMap<K, V> map = new TreeMap<>();
|
TreeMap<K, V> map = new TreeMap<>();
|
||||||
fillIntoEmptyMap(map, c, keyGenerator);
|
fillIntoEmptyMap(map, c, keyGenerator);
|
||||||
return map;
|
return map;
|
||||||
|
|
|
@ -55,16 +55,16 @@ public class OptionalUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 {@code Optional<Integer>} 转为 {@link OptionalInt}。
|
* 将 {@code Optional<Integer>} 对象转为 {@link OptionalInt} 对象。
|
||||||
* <p>
|
* <p>
|
||||||
* {@code Optional<Integer>} 将整数包装了两次,改为使用 {@link OptionalInt} 包装其中的整数数据。
|
* {@code Optional<Integer>} 将整数包装了两次,改为使用 {@link OptionalInt} 包装其中的整数数据。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param value 包装对象
|
* @param optionalObj {@code Optional<Integer>} 对象
|
||||||
* @return {@link OptionalInt} 实例
|
* @return {@link OptionalInt} 实例
|
||||||
*/
|
*/
|
||||||
public static OptionalInt toOptionalInt(Optional<Integer> objectOptional) {
|
public static OptionalInt toOptionalInt(Optional<Integer> optionalObj) {
|
||||||
return optionalOf(objectOptional.orElse(null));
|
return optionalOf(optionalObj.orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,11 +87,11 @@ public class OptionalUtil {
|
||||||
* {@code Optional<Long>} 将整数包装了两次,改为使用 {@link OptionalLong} 包装其中的整数数据。
|
* {@code Optional<Long>} 将整数包装了两次,改为使用 {@link OptionalLong} 包装其中的整数数据。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param value 包装对象
|
* @param optionalObj 包装对象
|
||||||
* @return {@link OptionalLong} 实例
|
* @return {@link OptionalLong} 实例
|
||||||
*/
|
*/
|
||||||
public static OptionalLong toOptionalLong(Optional<Long> objectOptional) {
|
public static OptionalLong toOptionalLong(Optional<Long> optionalObj) {
|
||||||
return optionalOf(objectOptional.orElse(null));
|
return optionalOf(optionalObj.orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,11 +114,11 @@ public class OptionalUtil {
|
||||||
* {@code Optional<Double>} 将整数包装了两次,改为使用 {@link OptionalDouble} 包装其中的整数数据。
|
* {@code Optional<Double>} 将整数包装了两次,改为使用 {@link OptionalDouble} 包装其中的整数数据。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param value 包装对象
|
* @param optionalObj 包装对象
|
||||||
* @return {@link OptionalDouble} 实例
|
* @return {@link OptionalDouble} 实例
|
||||||
*/
|
*/
|
||||||
public static OptionalDouble toOptionalDouble(Optional<Double> objectOptional) {
|
public static OptionalDouble toOptionalDouble(Optional<Double> optionalObj) {
|
||||||
return optionalOf(objectOptional.orElse(null));
|
return optionalOf(optionalObj.orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,10 +51,11 @@ public class PagingAndSortingQueryParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PagingAndSortingQueryParams(String... sortableColNames) {
|
public PagingAndSortingQueryParams(String... sortableColNames) {
|
||||||
|
Set<String> sortableColNameSet = new HashSet<>(sortableColNames.length);
|
||||||
for (String colName : sortableColNames) {
|
for (String colName : sortableColNames) {
|
||||||
Assert.isNotBlank(colName, "Column name must has text.");
|
Assert.isNotBlank(colName, "Column name must has text.");
|
||||||
|
sortableColNameSet.add(colName);
|
||||||
}
|
}
|
||||||
Set<String> sortableColNameSet = new HashSet<>(sortableColNames.length);
|
|
||||||
this.sortableColNames = Collections.unmodifiableSet(sortableColNameSet);
|
this.sortableColNames = Collections.unmodifiableSet(sortableColNameSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,10 +42,10 @@ public class SnowflakeIdGenerator {
|
||||||
private static final long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS);
|
private static final long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS);
|
||||||
|
|
||||||
/** 工作机器 ID (0~31) */
|
/** 工作机器 ID (0~31) */
|
||||||
private long workerId;
|
private final long workerId;
|
||||||
|
|
||||||
/** 数据中心 ID (0~31) */
|
/** 数据中心 ID (0~31) */
|
||||||
private long datacenterId;
|
private final long datacenterId;
|
||||||
|
|
||||||
/** 毫秒内序列 (0~4095) */
|
/** 毫秒内序列 (0~4095) */
|
||||||
private long sequence = 0L;
|
private long sequence = 0L;
|
||||||
|
@ -78,7 +78,6 @@ public class SnowflakeIdGenerator {
|
||||||
* 获得下一个ID (该方法是线程安全的)
|
* 获得下一个ID (该方法是线程安全的)
|
||||||
*
|
*
|
||||||
* @return SnowflakeId
|
* @return SnowflakeId
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
*/
|
||||||
public synchronized long nextId() {
|
public synchronized long nextId() {
|
||||||
long timestamp = timeGen();
|
long timestamp = timeGen();
|
||||||
|
|
|
@ -28,7 +28,7 @@ class SimpleJdbcTemplateTests {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SimpleJdbcTemplateTests.class);
|
private static final Logger log = LoggerFactory.getLogger(SimpleJdbcTemplateTests.class);
|
||||||
|
|
||||||
DataSource dataSource;
|
final DataSource dataSource;
|
||||||
|
|
||||||
String[] cStruct = {
|
String[] cStruct = {
|
||||||
"id",
|
"id",
|
||||||
|
|
|
@ -31,7 +31,7 @@ class TreeBuilderTests {
|
||||||
MenuItem.of("C", "C2", "二级菜单C2", "/c/c2"),
|
MenuItem.of("C", "C2", "二级菜单C2", "/c/c2"),
|
||||||
MenuItem.of("C", "C3", "二级菜单C3", "/c/c3")
|
MenuItem.of("C", "C3", "二级菜单C3", "/c/c3")
|
||||||
);
|
);
|
||||||
List<Menu> menuTree = new TreeBuilder<Menu, String>(
|
List<Menu> menuTree = new TreeBuilder<>(
|
||||||
menus,
|
menus,
|
||||||
Menu::getMenuCode,
|
Menu::getMenuCode,
|
||||||
Menu::getParentMenuCode,
|
Menu::getParentMenuCode,
|
||||||
|
|
Loading…
Reference in New Issue