new-1.1
This commit is contained in:
parent
706de6f042
commit
c6b53cb30b
35
pom.xml
35
pom.xml
|
@ -81,14 +81,13 @@
|
|||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.20.4-R0.1-SNAPSHOT</version>
|
||||
<version>1.20.6-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.20.4</version>
|
||||
<classifier>nms</classifier>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-nms</artifactId>
|
||||
<version>1.20.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -112,34 +111,24 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.26.2</version>
|
||||
<version>1.27.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.18.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.luben</groupId>
|
||||
<artifactId>zstd-jni</artifactId>
|
||||
<version>1.5.6-3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>4.0.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.46.0.0</version>
|
||||
<scope>provided</scope>
|
||||
<version>1.5.6-9</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>5.1.3</version>
|
||||
<scope>provided</scope>
|
||||
<version>5.2.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -9,7 +9,6 @@ import net.byteflux.libby.*;
|
|||
import net.byteflux.libby.logging.LogLevel;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
public final class ElementOriginLib extends JavaPlugin {
|
||||
|
||||
|
@ -18,19 +17,25 @@ public final class ElementOriginLib extends JavaPlugin {
|
|||
|
||||
private static Logger logger = Logger.getLogger(ElementOriginLib.class);
|
||||
|
||||
private static RedisIO redisIO;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
|
||||
loadLibraries();
|
||||
|
||||
Lang.registerLangFile(this);
|
||||
Lang.reload();
|
||||
|
||||
new GuiHandlerListener(this);
|
||||
new PlayerChatInputListener(this);
|
||||
|
||||
Lang.registerLangFile(this);
|
||||
Lang.reload();
|
||||
|
||||
redisIO = new RedisIO();
|
||||
redisIO.init(this);
|
||||
|
||||
logger.info("Successfully load ElementOriginLib v"+getPluginMeta().getVersion());
|
||||
|
||||
}
|
||||
|
||||
private void loadLibraries() {
|
||||
|
@ -38,11 +43,11 @@ public final class ElementOriginLib extends JavaPlugin {
|
|||
LibraryManager libraryManager = new BukkitLibraryManager(this);
|
||||
libraryManager.addMavenCentral();
|
||||
libraryManager.setLogLevel(LogLevel.WARN);
|
||||
libraryManager.loadLibrary(Library.builder().groupId("org{}apache{}commons").artifactId("commons-compress").version("1.26.2").build());
|
||||
libraryManager.loadLibrary(Library.builder().groupId("com{}github{}luben").artifactId("zstd-jni").version("1.5.6-3").build());
|
||||
libraryManager.loadLibrary(Library.builder().groupId("com{}zaxxer").artifactId("HikariCP").version("4.0.3").build());
|
||||
libraryManager.loadLibrary(Library.builder().groupId("org{}xerial").artifactId("sqlite-jdbc").version("3.46.0.0").build());
|
||||
libraryManager.loadLibrary(Library.builder().groupId("redis{}clients").id("jedis").artifactId("jedis").version("5.1.3").build());
|
||||
libraryManager.loadLibrary(Library.builder().groupId("org{}apache{}commons").artifactId("commons-compress").version("1.27.1").build());
|
||||
// libraryManager.loadLibrary(Library.builder().groupId("com{}github{}luben").artifactId("zstd-jni").version("1.5.6-9").build());
|
||||
// libraryManager.loadLibrary(Library.builder().groupId("com{}zaxxer").artifactId("HikariCP").version("6.2.1").build());
|
||||
// libraryManager.loadLibrary(Library.builder().groupId("org{}xerial").artifactId("sqlite-jdbc").version("3.46.0.0").build());
|
||||
// libraryManager.loadLibrary(Library.builder().groupId("redis{}clients").id("jedis").artifactId("jedis").version("5.2.0").build());
|
||||
logger.info("Successfully loaded libraries.");
|
||||
}
|
||||
|
||||
|
@ -50,6 +55,10 @@ public final class ElementOriginLib extends JavaPlugin {
|
|||
public void onDisable() {
|
||||
}
|
||||
|
||||
public static RedisIO getRedisIO() {
|
||||
return redisIO;
|
||||
}
|
||||
|
||||
public static ElementOriginLib inst() {
|
||||
return instance;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package com.io.yutian.elementoriginlib.datasync;
|
||||
|
||||
import com.io.yutian.elementoriginlib.ElementOriginLib;
|
||||
import com.io.yutian.elementoriginlib.serialize.SerializeHelper;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
public class DataSyncHelper {
|
||||
|
||||
public static void saveData(String key, Object value) {
|
||||
String strValue = SerializeHelper.serialize(value);
|
||||
try (Jedis jedis = ElementOriginLib.getRedisIO().getJedisPool().getResource()) {
|
||||
jedis.set(key, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T getData(String key, Class<T> clazz) {
|
||||
try (Jedis jedis = ElementOriginLib.getRedisIO().getJedisPool().getResource()) {
|
||||
if (!jedis.exists(key)) {
|
||||
return null;
|
||||
}
|
||||
String strValue = jedis.get(key);
|
||||
if (strValue == null) {
|
||||
return null;
|
||||
}
|
||||
return SerializeHelper.deserialize(strValue, clazz);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package com.io.yutian.elementoriginlib.gui.button;
|
||||
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTString;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagString;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class ItemButton extends Button {
|
|||
|
||||
public boolean isItem(ItemStack item) {
|
||||
NBTItem nbtItem = new NBTItem(item);
|
||||
return nbtItem.has("gui_meta", NBTString.TYPE_ID) && ((NBTString) nbtItem.get("gui_meta")).getString().equals("item_button");
|
||||
return nbtItem.has("gui_meta", TagString.TYPE_ID) && ((TagString) nbtItem.get("gui_meta")).getString().equals("item_button");
|
||||
}
|
||||
|
||||
public ItemButton clickItem(BiConsumer<Player, ItemStack> consumer) {
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.io.yutian.elementoriginlib.item.stat.type;
|
|||
import com.io.yutian.elementoriginlib.item.OriginItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.BooleanData;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTByte;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagByte;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -23,7 +23,7 @@ public abstract class BooleanStat extends ItemStat<BooleanData> {
|
|||
@Nullable
|
||||
@Override
|
||||
public BooleanData getLoadedNBT(@NotNull NBTItem nbtItem) {
|
||||
return new BooleanData(((NBTByte) nbtItem.get(getNBTPath())).getByte() == 1);
|
||||
return new BooleanData(((TagByte) nbtItem.get(getNBTPath())).getByte() == 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.io.yutian.elementoriginlib.item.stat.type;
|
|||
import com.io.yutian.elementoriginlib.item.OriginItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.DoubleData;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTDouble;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagDouble;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -23,7 +23,7 @@ public abstract class DoubleStat extends ItemStat<DoubleData> {
|
|||
@Nullable
|
||||
@Override
|
||||
public DoubleData getLoadedNBT(@NotNull NBTItem nbtItem) {
|
||||
return new DoubleData(((NBTDouble) nbtItem.get(getNBTPath())).getDouble());
|
||||
return new DoubleData(((TagDouble) nbtItem.get(getNBTPath())).getDouble());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.io.yutian.elementoriginlib.item.stat.type;
|
|||
import com.io.yutian.elementoriginlib.item.OriginItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.IntData;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTInt;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagInt;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -23,7 +23,7 @@ public abstract class IntStat extends ItemStat<IntData> {
|
|||
@Nullable
|
||||
@Override
|
||||
public IntData getLoadedNBT(@NotNull NBTItem nbtItem) {
|
||||
return new IntData(((NBTInt)nbtItem.get(getNBTPath())).getInt());
|
||||
return new IntData(((TagInt)nbtItem.get(getNBTPath())).getInt());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import com.io.yutian.elementoriginlib.item.OriginItemStackBuilder;
|
|||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.StringListData;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTList;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTString;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagList;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagString;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -21,21 +21,21 @@ public abstract class StringListStat extends ItemStat<StringListData> {
|
|||
@Override
|
||||
public void whenApplied(@NotNull OriginItemStackBuilder itemStackBuilder, @NotNull StringListData statData) {
|
||||
NBTItem nbtItem = itemStackBuilder.getNBTItem();
|
||||
NBTList<NBTString> nbtList = new NBTList<>();
|
||||
statData.getList().forEach(s -> nbtList.add(new NBTString(s)));
|
||||
nbtItem.editTag(nbtCompound -> nbtCompound.put(getNBTPath(), nbtList));
|
||||
TagList<TagString> tagList = new TagList<>();
|
||||
statData.getList().forEach(s -> tagList.add(new TagString(s)));
|
||||
nbtItem.editTag(nbtCompound -> nbtCompound.put(getNBTPath(), tagList));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StringListData getLoadedNBT(@NotNull NBTItem nbtItem) {
|
||||
if (!nbtItem.has(getNBTPath(), NBTList.TYPE_ID)) {
|
||||
if (!nbtItem.has(getNBTPath(), TagList.TYPE_ID)) {
|
||||
return new StringListData(new ArrayList<>());
|
||||
}
|
||||
NBTList<NBTString> nbtList = (NBTList<NBTString>) nbtItem.get(getNBTPath());
|
||||
TagList<TagString> tagList = (TagList<TagString>) nbtItem.get(getNBTPath());
|
||||
List<String> list = new ArrayList<>();
|
||||
for (int i = 0; i < nbtList.size(); i++) {
|
||||
list.add(nbtList.get(i).getString());
|
||||
for (int i = 0; i < tagList.size(); i++) {
|
||||
list.add(tagList.get(i).getString());
|
||||
}
|
||||
return new StringListData(list);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.io.yutian.elementoriginlib.item.OriginItemStackBuilder;
|
|||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.StringData;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTString;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagString;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -24,7 +24,7 @@ public abstract class StringStat extends ItemStat<StringData> {
|
|||
@Nullable
|
||||
@Override
|
||||
public StringData getLoadedNBT(@NotNull NBTItem nbtItem) {
|
||||
return new StringData(((NBTString) nbtItem.get(getNBTPath())).getString());
|
||||
return new StringData(((TagString) nbtItem.get(getNBTPath())).getString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.io.yutian.elementoriginlib.item.OriginItemStackBuilder;
|
|||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.UUIDData;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTString;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagString;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -25,7 +25,7 @@ public abstract class UUIDStat extends ItemStat<UUIDData> {
|
|||
@Nullable
|
||||
@Override
|
||||
public UUIDData getLoadedNBT(@NotNull NBTItem nbtItem) {
|
||||
return new UUIDData(UUID.fromString(((NBTString) nbtItem.get(getNBTPath())).getString()));
|
||||
return new UUIDData(UUID.fromString(((TagString) nbtItem.get(getNBTPath())).getString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
import net.minecraft.nbt.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface INBT {
|
||||
|
||||
Object getValue();
|
||||
|
||||
byte getTypeId();
|
||||
|
||||
private static String getNBTTag(byte typeByte) {
|
||||
return switch (typeByte) {
|
||||
case 1 -> "NBTTagByte";
|
||||
case 2 -> "NBTTagShort";
|
||||
case 3 -> "NBTTagInt";
|
||||
case 4 -> "NBTTagLong";
|
||||
case 5 -> "NBTTagFloat";
|
||||
case 6 -> "NBTTagDouble";
|
||||
case 7 -> "NBTTagByteArray";
|
||||
case 8 -> "NBTTagString";
|
||||
case 9 -> "NBTTagList";
|
||||
case 10 -> "NBTTagCompound";
|
||||
case 11 -> "NBTTagIntArray";
|
||||
case 12 -> "NBTTagLongArray";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
static INBT asObject(Object object) {
|
||||
if (object instanceof Byte b) {
|
||||
return new NBTByte(b);
|
||||
} else if (object instanceof Short value) {
|
||||
return new NBTShort(value);
|
||||
} else if (object instanceof Integer value) {
|
||||
return new NBTInt(value);
|
||||
} else if (object instanceof Long value) {
|
||||
return new NBTLong(value);
|
||||
} else if (object instanceof Float value) {
|
||||
return new NBTFloat(value);
|
||||
} else if (object instanceof Double value) {
|
||||
return new NBTDouble(value);
|
||||
} else if (object instanceof byte[] value) {
|
||||
return new NBTByteArray(value);
|
||||
} else if (object instanceof String value) {
|
||||
return new NBTString(value);
|
||||
} else if (object instanceof int[] value) {
|
||||
return new NBTIntArray(value);
|
||||
} else if (object instanceof long[] value) {
|
||||
return new NBTLongArray(value);
|
||||
} else if (object instanceof Boolean b) {
|
||||
return new NBTByte((byte) (b ? 1 : 0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static net.minecraft.nbt.NBTBase asNMS(INBT nbt) {
|
||||
byte type = nbt.getTypeId();
|
||||
switch (type) {
|
||||
case 1 -> {
|
||||
NBTByte nbtByte = (NBTByte) nbt;
|
||||
return NBTTagByte.a(nbtByte.getByte());
|
||||
}
|
||||
case 2 -> {
|
||||
NBTShort nbtShort = (NBTShort) nbt;
|
||||
return NBTTagShort.a(nbtShort.getShort());
|
||||
}
|
||||
case 3 -> {
|
||||
NBTInt nbtInt = (NBTInt) nbt;
|
||||
return NBTTagInt.a(nbtInt.getInt());
|
||||
}
|
||||
case 4 -> {
|
||||
NBTLong nbtLong = (NBTLong) nbt;
|
||||
return NBTTagLong.a(nbtLong.getLong());
|
||||
}
|
||||
case 5 -> {
|
||||
NBTFloat nbtfloat = (NBTFloat) nbt;
|
||||
return NBTTagFloat.a(nbtfloat.getFloat());
|
||||
}
|
||||
case 6 -> {
|
||||
NBTDouble nbtDouble = (NBTDouble) nbt;
|
||||
return NBTTagDouble.a(nbtDouble.getDouble());
|
||||
}
|
||||
case 7 -> {
|
||||
NBTByteArray nbtByteArray = (NBTByteArray) nbt;
|
||||
return new NBTTagByteArray(nbtByteArray.getByteArray());
|
||||
}
|
||||
case 8 -> {
|
||||
NBTString nbtString = (NBTString) nbt;
|
||||
return NBTTagString.a(nbtString.getString());
|
||||
}
|
||||
case 9 -> {
|
||||
NBTList nbtTagList = (NBTList) nbt;
|
||||
List<net.minecraft.nbt.NBTBase> list = new ArrayList<>();
|
||||
for (Object base : nbtTagList.getList()) {
|
||||
list.add(asNMS((INBT) base));
|
||||
}
|
||||
NBTTagList nbtTagList1 = new NBTTagList();
|
||||
for (net.minecraft.nbt.NBTBase nbt1 : list) {
|
||||
nbtTagList1.add(nbt1);
|
||||
}
|
||||
return nbtTagList1;
|
||||
}
|
||||
case 10 -> {
|
||||
NBTCompound nbtCompound = (NBTCompound) nbt;
|
||||
NBTTagCompound nbtTagCompound = new NBTTagCompound();
|
||||
for (String key : nbtCompound.keySet()) {
|
||||
INBT nbt1 = nbtCompound.get(key);
|
||||
nbtTagCompound.a(key, asNMS(nbt1));
|
||||
}
|
||||
return nbtTagCompound;
|
||||
}
|
||||
case 11 -> {
|
||||
NBTIntArray nbtIntArray = (NBTIntArray) nbt;
|
||||
return new NBTTagIntArray(nbtIntArray.getIntArray());
|
||||
}
|
||||
case 12 -> {
|
||||
NBTLongArray nbtLongArray = (NBTLongArray) nbt;
|
||||
return new NBTTagLongArray(nbtLongArray.getLongArray());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static INBT as(net.minecraft.nbt.NBTBase nbtBase) {
|
||||
byte type = nbtBase.b();
|
||||
switch (type) {
|
||||
case 1:
|
||||
NBTTagByte nbtTagByte = (NBTTagByte) nbtBase;
|
||||
return new NBTByte(nbtTagByte.i());
|
||||
case 2:
|
||||
NBTTagShort nbtTagShort = (NBTTagShort) nbtBase;
|
||||
return new NBTShort(nbtTagShort.h());
|
||||
case 3:
|
||||
NBTTagInt nbtTagInt = (NBTTagInt) nbtBase;
|
||||
return new NBTInt(nbtTagInt.g());
|
||||
case 4:
|
||||
NBTTagLong nbtTagLong = (NBTTagLong) nbtBase;
|
||||
return new NBTLong(nbtTagLong.f());
|
||||
case 5:
|
||||
NBTTagFloat nbtTagFloat = (NBTTagFloat) nbtBase;
|
||||
return new NBTFloat(nbtTagFloat.k());
|
||||
case 6:
|
||||
NBTTagDouble nbtTagDouble = (NBTTagDouble) nbtBase;
|
||||
return new NBTDouble(nbtTagDouble.j());
|
||||
case 7:
|
||||
NBTTagByteArray tagByteArray = (NBTTagByteArray) nbtBase;
|
||||
return new NBTByteArray(tagByteArray.e());
|
||||
case 8:
|
||||
NBTTagString nbtTagString = (NBTTagString) nbtBase;
|
||||
return new NBTString(nbtTagString.t_());
|
||||
case 9:
|
||||
NBTTagList nbtTagList = (NBTTagList) nbtBase;
|
||||
List<INBT> list = new ArrayList<>();
|
||||
for (net.minecraft.nbt.NBTBase base : nbtTagList) {
|
||||
list.add(as(base));
|
||||
}
|
||||
return new NBTList(list);
|
||||
case 10:
|
||||
NBTTagCompound nbtTagCompound = (NBTTagCompound) nbtBase;
|
||||
Map<String, INBT> map = new HashMap<>();
|
||||
for (String key : nbtTagCompound.e()) {
|
||||
map.put(key, as(nbtTagCompound.c(key)));
|
||||
}
|
||||
return new NBTCompound(map);
|
||||
case 11:
|
||||
NBTTagIntArray nbtTagIntArray = (NBTTagIntArray) nbtBase;
|
||||
return new NBTIntArray(nbtTagIntArray.g());
|
||||
case 12:
|
||||
NBTTagLongArray nbtTagLongArray = (NBTTagLongArray) nbtBase;
|
||||
return new NBTLongArray(nbtTagLongArray.g());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
180
src/main/java/com/io/yutian/elementoriginlib/nbt/ITag.java
Normal file
180
src/main/java/com/io/yutian/elementoriginlib/nbt/ITag.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
import net.minecraft.nbt.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ITag {
|
||||
|
||||
Object getValue();
|
||||
|
||||
byte getTypeId();
|
||||
|
||||
private static String getTag(byte typeByte) {
|
||||
return switch (typeByte) {
|
||||
case 1 -> "TagByte";
|
||||
case 2 -> "TagShort";
|
||||
case 3 -> "TagInt";
|
||||
case 4 -> "TagLong";
|
||||
case 5 -> "TagFloat";
|
||||
case 6 -> "TagDouble";
|
||||
case 7 -> "TagByteArray";
|
||||
case 8 -> "TagString";
|
||||
case 9 -> "TagList";
|
||||
case 10 -> "TagCompound";
|
||||
case 11 -> "TagIntArray";
|
||||
case 12 -> "TagLongArray";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
static ITag asObject(Object object) {
|
||||
if (object instanceof Byte b) {
|
||||
return new TagByte(b);
|
||||
} else if (object instanceof Short value) {
|
||||
return new TagShort(value);
|
||||
} else if (object instanceof Integer value) {
|
||||
return new TagInt(value);
|
||||
} else if (object instanceof Long value) {
|
||||
return new TagLong(value);
|
||||
} else if (object instanceof Float value) {
|
||||
return new TagFloat(value);
|
||||
} else if (object instanceof Double value) {
|
||||
return new TagDouble(value);
|
||||
} else if (object instanceof byte[] value) {
|
||||
return new TagByteArray(value);
|
||||
} else if (object instanceof String value) {
|
||||
return new TagString(value);
|
||||
} else if (object instanceof int[] value) {
|
||||
return new TagIntArray(value);
|
||||
} else if (object instanceof long[] value) {
|
||||
return new TagLongArray(value);
|
||||
} else if (object instanceof Boolean b) {
|
||||
return new TagByte((byte) (b ? 1 : 0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static net.minecraft.nbt.Tag asNMS(ITag nbt) {
|
||||
byte type = nbt.getTypeId();
|
||||
switch (type) {
|
||||
case 1 -> {
|
||||
TagByte tagByte = (TagByte) nbt;
|
||||
return ByteTag.valueOf(tagByte.getByte());
|
||||
}
|
||||
case 2 -> {
|
||||
TagShort nbtShort = (TagShort) nbt;
|
||||
return ShortTag.valueOf(nbtShort.getShort());
|
||||
}
|
||||
case 3 -> {
|
||||
TagInt tagInt = (TagInt) nbt;
|
||||
return IntTag.valueOf(tagInt.getInt());
|
||||
}
|
||||
case 4 -> {
|
||||
TagLong tagLong = (TagLong) nbt;
|
||||
return LongTag.valueOf(tagLong.getLong());
|
||||
}
|
||||
case 5 -> {
|
||||
TagFloat nbtfloat = (TagFloat) nbt;
|
||||
return FloatTag.valueOf(nbtfloat.getFloat());
|
||||
}
|
||||
case 6 -> {
|
||||
TagDouble tagDouble = (TagDouble) nbt;
|
||||
return DoubleTag.valueOf(tagDouble.getDouble());
|
||||
}
|
||||
case 7 -> {
|
||||
TagByteArray tagByteArray = (TagByteArray) nbt;
|
||||
return new ByteArrayTag(tagByteArray.getByteArray());
|
||||
}
|
||||
case 8 -> {
|
||||
TagString tagString = (TagString) nbt;
|
||||
return StringTag.valueOf(tagString.getString());
|
||||
}
|
||||
case 9 -> {
|
||||
TagList nbtTagList = (TagList) nbt;
|
||||
List<net.minecraft.nbt.Tag> list = new ArrayList<>();
|
||||
for (Object base : nbtTagList.getList()) {
|
||||
list.add(asNMS((ITag) base));
|
||||
}
|
||||
ListTag nbtTagList1 = new ListTag();
|
||||
for (net.minecraft.nbt.Tag nbt1 : list) {
|
||||
nbtTagList1.add(nbt1);
|
||||
}
|
||||
return nbtTagList1;
|
||||
}
|
||||
case 10 -> {
|
||||
TagCompound tagCompound = (TagCompound) nbt;
|
||||
CompoundTag nbtTagCompound = new CompoundTag();
|
||||
for (String key : tagCompound.keySet()) {
|
||||
ITag nbt1 = tagCompound.get(key);
|
||||
nbtTagCompound.put(key, asNMS(nbt1));
|
||||
}
|
||||
return nbtTagCompound;
|
||||
}
|
||||
case 11 -> {
|
||||
TagIntArray tagIntArray = (TagIntArray) nbt;
|
||||
return new IntArrayTag(tagIntArray.getIntArray());
|
||||
}
|
||||
case 12 -> {
|
||||
TagLongArray tagLongArray = (TagLongArray) nbt;
|
||||
return new LongArrayTag(tagLongArray.getLongArray());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static ITag as(net.minecraft.nbt.Tag tag) {
|
||||
byte type = tag.getId();
|
||||
switch (type) {
|
||||
case 1:
|
||||
ByteTag nbtTagByte = (ByteTag) tag;
|
||||
return new TagByte(nbtTagByte.getAsByte());
|
||||
case 2:
|
||||
ShortTag nbtTagShort = (ShortTag) tag;
|
||||
return new TagShort(nbtTagShort.getAsShort());
|
||||
case 3:
|
||||
IntTag nbtTagInt = (IntTag) tag;
|
||||
return new TagInt(nbtTagInt.getAsInt());
|
||||
case 4:
|
||||
LongTag nbtTagLong = (LongTag) tag;
|
||||
return new TagLong(nbtTagLong.getAsLong());
|
||||
case 5:
|
||||
FloatTag nbtTagFloat = (FloatTag) tag;
|
||||
return new TagFloat(nbtTagFloat.getAsFloat());
|
||||
case 6:
|
||||
DoubleTag nbtTagDouble = (DoubleTag) tag;
|
||||
return new TagDouble(nbtTagDouble.getAsDouble());
|
||||
case 7:
|
||||
ByteArrayTag tagByteArray = (ByteArrayTag) tag;
|
||||
return new TagByteArray(tagByteArray.getAsByteArray());
|
||||
case 8:
|
||||
StringTag nbtTagString = (StringTag) tag;
|
||||
return new TagString(nbtTagString.getAsString());
|
||||
case 9:
|
||||
ListTag nbtTagList = (ListTag) tag;
|
||||
List<ITag> list = new ArrayList<>();
|
||||
for (net.minecraft.nbt.Tag base : nbtTagList) {
|
||||
list.add(as(base));
|
||||
}
|
||||
return new TagList(list);
|
||||
case 10:
|
||||
CompoundTag nbtTagCompound = (CompoundTag) tag;
|
||||
Map<String, ITag> map = new HashMap<>();
|
||||
for (String key : nbtTagCompound.getAllKeys()) {
|
||||
map.put(key, as(nbtTagCompound.get(key)));
|
||||
}
|
||||
return new TagCompound(map);
|
||||
case 11:
|
||||
IntArrayTag nbtTagIntArray = (IntArrayTag) tag;
|
||||
return new TagIntArray(nbtTagIntArray.getAsIntArray());
|
||||
case 12:
|
||||
LongArrayTag nbtTagLongArray = (LongArrayTag) tag;
|
||||
return new TagLongArray(nbtTagLongArray.getAsLongArray());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class NBTHelper {
|
||||
|
||||
@Nullable
|
||||
public static INBT convert(Object object) {
|
||||
if (object instanceof Byte) {
|
||||
return new NBTByte((byte) object);
|
||||
} else if (object instanceof Short) {
|
||||
return new NBTShort((short) object);
|
||||
} else if (object instanceof Integer) {
|
||||
return new NBTInt((int) object);
|
||||
} else if (object instanceof Long) {
|
||||
return new NBTLong((long) object);
|
||||
} else if (object instanceof Float) {
|
||||
return new NBTFloat((float) object);
|
||||
} else if (object instanceof Double) {
|
||||
return new NBTDouble((double) object);
|
||||
} else if (object instanceof byte[]) {
|
||||
return new NBTByteArray((byte[]) object);
|
||||
} else if (object instanceof String) {
|
||||
return new NBTString((String) object);
|
||||
} else if (object instanceof int[]) {
|
||||
return new NBTIntArray((int[]) object);
|
||||
} else if (object instanceof long[]) {
|
||||
return new NBTLongArray((long[]) object);
|
||||
} else if (object instanceof Boolean) {
|
||||
return new NBTByte((byte) ((boolean)object ? 1 : 0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object convertNMSNBT(INBT nbt) {
|
||||
return INBT.asNMS(nbt);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||
import com.io.yutian.elementoriginlib.serialize.serializers.ItemStackDeserializer;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -21,38 +24,38 @@ public class NBTItem {
|
|||
}
|
||||
|
||||
@NotNull
|
||||
public NBTCompound getTag() {
|
||||
NBTTagCompound tag = nmsItemStack.w();
|
||||
public TagCompound getTag() {
|
||||
CompoundTag tag = nmsItemStack.getComponents().get(DataComponents.CUSTOM_DATA).getUnsafe();
|
||||
if (tag == null) {
|
||||
tag = new NBTTagCompound();
|
||||
tag = new CompoundTag();
|
||||
}
|
||||
return (NBTCompound) INBT.as(tag);
|
||||
return (TagCompound) ITag.as(tag);
|
||||
}
|
||||
|
||||
public boolean has(String key) {
|
||||
NBTCompound nbtCompound = getTag();
|
||||
return nbtCompound.hasKey(key);
|
||||
TagCompound tagCompound = getTag();
|
||||
return tagCompound.hasKey(key);
|
||||
}
|
||||
|
||||
public boolean has(String key, int type) {
|
||||
NBTCompound nbtCompound = getTag();
|
||||
return nbtCompound.hasKey(key, type);
|
||||
TagCompound tagCompound = getTag();
|
||||
return tagCompound.hasKey(key, type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public INBT get(String key) {
|
||||
NBTCompound nbtCompound = getTag();
|
||||
return nbtCompound.hasKey(key) ? nbtCompound.get(key) : null;
|
||||
public ITag get(String key) {
|
||||
TagCompound tagCompound = getTag();
|
||||
return tagCompound.hasKey(key) ? tagCompound.get(key) : null;
|
||||
}
|
||||
|
||||
public void editTag(Consumer<NBTCompound> consumer) {
|
||||
NBTCompound tag = getTag();
|
||||
public void editTag(Consumer<TagCompound> consumer) {
|
||||
TagCompound tag = getTag();
|
||||
consumer.accept(tag);
|
||||
setTag(tag);
|
||||
}
|
||||
|
||||
public void setTag(NBTCompound nbtCompound) {
|
||||
nmsItemStack.c((NBTTagCompound) INBT.asNMS(nbtCompound));
|
||||
public void setTag(TagCompound tagCompound) {
|
||||
nmsItemStack.set(DataComponents.CUSTOM_DATA, CustomData.of((CompoundTag) ITag.asNMS(tagCompound)));
|
||||
resultItemStack = CraftItemStack.asBukkitCopy(nmsItemStack);
|
||||
}
|
||||
|
||||
|
@ -72,8 +75,8 @@ public class NBTItem {
|
|||
return new NBTItem(itemStack);
|
||||
}
|
||||
|
||||
public static NBTItem build(NBTCompound nbtCompound) {
|
||||
net.minecraft.world.item.ItemStack nmsItemStack = net.minecraft.world.item.ItemStack.a((NBTTagCompound) INBT.asNMS(nbtCompound));
|
||||
public static NBTItem build(TagCompound tagCompound) {
|
||||
net.minecraft.world.item.ItemStack nmsItemStack = net.minecraft.world.item.ItemStack.parse(ItemStackDeserializer.getRegistry(), ITag.asNMS(tagCompound)).get();
|
||||
return new NBTItem(CraftItemStack.asBukkitCopy(nmsItemStack));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
public class NBTByte extends NBTNumber {
|
||||
public class TagByte extends TagNumber {
|
||||
|
||||
public static byte TYPE_ID = 1;
|
||||
|
||||
private byte value;
|
||||
|
||||
public NBTByte(byte value) {
|
||||
public TagByte(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTByte() {
|
||||
public TagByte() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,8 +53,8 @@ public class NBTByte extends NBTNumber {
|
|||
return this.value;
|
||||
}
|
||||
|
||||
public static NBTByte a(boolean var0) {
|
||||
return var0 ? new NBTByte((byte) 1) : new NBTByte((byte) 0);
|
||||
public static TagByte a(boolean var0) {
|
||||
return var0 ? new TagByte((byte) 1) : new TagByte((byte) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,8 +62,8 @@ public class NBTByte extends NBTNumber {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTByte nbtByte = (NBTByte) o;
|
||||
return value == nbtByte.value;
|
||||
TagByte tagByte = (TagByte) o;
|
||||
return value == tagByte.value;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -2,13 +2,13 @@ package com.io.yutian.elementoriginlib.nbt;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NBTByteArray implements INBT {
|
||||
public class TagByteArray implements ITag {
|
||||
|
||||
public static byte TYPE_ID = 7;
|
||||
|
||||
private byte[] value;
|
||||
|
||||
public NBTByteArray(byte[] value) {
|
||||
public TagByteArray(byte[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ public class NBTByteArray implements INBT {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTByteArray that = (NBTByteArray) o;
|
||||
TagByteArray that = (TagByteArray) o;
|
||||
return Arrays.equals(value, that.value);
|
||||
}
|
||||
|
|
@ -2,16 +2,16 @@ package com.io.yutian.elementoriginlib.nbt;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
public class NBTCompound implements INBT {
|
||||
public class TagCompound implements ITag {
|
||||
|
||||
public static byte TYPE_ID = 10;
|
||||
|
||||
private Map<String, INBT> nbtMap = new HashMap<>();
|
||||
private Map<String, ITag> nbtMap = new HashMap<>();
|
||||
|
||||
public NBTCompound() {
|
||||
public TagCompound() {
|
||||
}
|
||||
|
||||
public NBTCompound(Map<String, INBT> nbtMap) {
|
||||
public TagCompound(Map<String, ITag> nbtMap) {
|
||||
this.nbtMap = nbtMap;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ public class NBTCompound implements INBT {
|
|||
return nbtMap.keySet();
|
||||
}
|
||||
|
||||
public Map<String, INBT> getMap() {
|
||||
public Map<String, ITag> getMap() {
|
||||
return nbtMap;
|
||||
}
|
||||
|
||||
|
@ -39,160 +39,160 @@ public class NBTCompound implements INBT {
|
|||
return this.nbtMap.containsKey(key) && this.nbtMap.get(key).getTypeId() == id;
|
||||
}
|
||||
|
||||
public NBTList getList(String key) {
|
||||
INBT list = this.nbtMap.get(key);
|
||||
public TagList getList(String key) {
|
||||
ITag list = this.nbtMap.get(key);
|
||||
if (list == null || list.getTypeId() != 9) {
|
||||
return null;
|
||||
}
|
||||
return (NBTList) list;
|
||||
return (TagList) list;
|
||||
}
|
||||
|
||||
public NBTCompound getCompound(String key) {
|
||||
INBT comound = this.nbtMap.get(key);
|
||||
public TagCompound getCompound(String key) {
|
||||
ITag comound = this.nbtMap.get(key);
|
||||
if (comound == null || comound.getTypeId() != 10) {
|
||||
return null;
|
||||
}
|
||||
return (NBTCompound) comound;
|
||||
return (TagCompound) comound;
|
||||
}
|
||||
|
||||
public INBT get(String key) {
|
||||
public ITag get(String key) {
|
||||
return this.nbtMap.get(key);
|
||||
}
|
||||
|
||||
public int getInt(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 3) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTInt) nbt).getInt();
|
||||
return ((TagInt) nbt).getInt();
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 8) {
|
||||
return null;
|
||||
}
|
||||
return ((NBTString) nbt).getString();
|
||||
return ((TagString) nbt).getString();
|
||||
}
|
||||
|
||||
public double getDouble(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 6) {
|
||||
return 0.0;
|
||||
}
|
||||
return ((NBTDouble) nbt).getDouble();
|
||||
return ((TagDouble) nbt).getDouble();
|
||||
}
|
||||
|
||||
public float getFloat(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 5) {
|
||||
return 0.0F;
|
||||
}
|
||||
return ((NBTFloat) nbt).getFloat();
|
||||
return ((TagFloat) nbt).getFloat();
|
||||
}
|
||||
|
||||
public short getShort(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 2) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTShort) nbt).getShort();
|
||||
return ((TagShort) nbt).getShort();
|
||||
}
|
||||
|
||||
public long getLong(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 4) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTLong) nbt).getLong();
|
||||
return ((TagLong) nbt).getLong();
|
||||
}
|
||||
|
||||
public byte getByte(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 1) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTByte) nbt).getByte();
|
||||
return ((TagByte) nbt).getByte();
|
||||
}
|
||||
|
||||
public NBTByteArray getByteArray(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
public TagByteArray getByteArray(String key) {
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 7) {
|
||||
return null;
|
||||
}
|
||||
return (NBTByteArray) nbt;
|
||||
return (TagByteArray) nbt;
|
||||
}
|
||||
|
||||
public NBTIntArray getIntArray(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
public TagIntArray getIntArray(String key) {
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 11) {
|
||||
return null;
|
||||
}
|
||||
return (NBTIntArray) nbt;
|
||||
return (TagIntArray) nbt;
|
||||
}
|
||||
|
||||
public NBTLongArray getLongArray(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
public TagLongArray getLongArray(String key) {
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 12) {
|
||||
return null;
|
||||
}
|
||||
return (NBTLongArray) nbt;
|
||||
return (TagLongArray) nbt;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 1) {
|
||||
return false;
|
||||
}
|
||||
return ((NBTByte) nbt).getByte() != 0;
|
||||
return ((TagByte) nbt).getByte() != 0;
|
||||
}
|
||||
|
||||
public UUID getUUID(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
ITag nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 11) {
|
||||
return null;
|
||||
}
|
||||
return a(((NBTIntArray) nbt).getIntArray());
|
||||
return a(((TagIntArray) nbt).getIntArray());
|
||||
}
|
||||
|
||||
public void put(String key, INBT nbt) {
|
||||
public void put(String key, ITag nbt) {
|
||||
this.nbtMap.put(key, nbt);
|
||||
}
|
||||
|
||||
public void putString(String key, String value) {
|
||||
put(key, new NBTString(value));
|
||||
put(key, new TagString(value));
|
||||
}
|
||||
|
||||
public void putInt(String key, int value) {
|
||||
put(key, new NBTInt(value));
|
||||
put(key, new TagInt(value));
|
||||
}
|
||||
|
||||
public void putShort(String key, short value) {
|
||||
put(key, new NBTShort(value));
|
||||
put(key, new TagShort(value));
|
||||
}
|
||||
|
||||
public void putDouble(String key, double value) {
|
||||
put(key, new NBTDouble(value));
|
||||
put(key, new TagDouble(value));
|
||||
}
|
||||
|
||||
public void putLong(String key, long value) {
|
||||
put(key, new NBTLong(value));
|
||||
put(key, new TagLong(value));
|
||||
}
|
||||
|
||||
public void putFloat(String key, float value) {
|
||||
put(key, new NBTFloat(value));
|
||||
put(key, new TagFloat(value));
|
||||
}
|
||||
|
||||
public void putByte(String key, byte value) {
|
||||
put(key, new NBTByte(value));
|
||||
put(key, new TagByte(value));
|
||||
}
|
||||
|
||||
public void putBoolean(String key, boolean value) {
|
||||
put(key, NBTByte.a(value));
|
||||
put(key, TagByte.a(value));
|
||||
}
|
||||
|
||||
public void putUUID(String key, UUID uuid) {
|
||||
put(key, new NBTIntArray(a(uuid)));
|
||||
put(key, new TagIntArray(a(uuid)));
|
||||
}
|
||||
|
||||
private static UUID a(int[] var0) {
|
||||
|
@ -224,19 +224,19 @@ public class NBTCompound implements INBT {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTCompound that = (NBTCompound) o;
|
||||
Map<String, INBT> nbtMap1 = this.nbtMap;
|
||||
Map<String, INBT> nbtMap2 = that.nbtMap;
|
||||
TagCompound that = (TagCompound) o;
|
||||
Map<String, ITag> nbtMap1 = this.nbtMap;
|
||||
Map<String, ITag> nbtMap2 = that.nbtMap;
|
||||
if (nbtMap1.size() != nbtMap2.size()) {
|
||||
return false;
|
||||
}
|
||||
for (Map.Entry<String, INBT> entry : nbtMap1.entrySet()) {
|
||||
for (Map.Entry<String, ITag> entry : nbtMap1.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
INBT value = entry.getValue();
|
||||
ITag value = entry.getValue();
|
||||
if (!nbtMap2.containsKey(key)) {
|
||||
return false;
|
||||
}
|
||||
INBT nbt2 = nbtMap2.get(key);
|
||||
ITag nbt2 = nbtMap2.get(key);
|
||||
Object object1 = value.getValue();
|
||||
Object object2 = nbt2.getValue();
|
||||
if (value == null && nbt2 != null) {
|
|
@ -1,16 +1,16 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
public class NBTDouble extends NBTNumber {
|
||||
public class TagDouble extends TagNumber {
|
||||
|
||||
public static byte TYPE_ID = 6;
|
||||
|
||||
private double value;
|
||||
|
||||
public NBTDouble(double value) {
|
||||
public TagDouble(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTDouble() {
|
||||
public TagDouble() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,8 +58,8 @@ public class NBTDouble extends NBTNumber {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTDouble nbtDouble = (NBTDouble) o;
|
||||
return Double.compare(value, nbtDouble.value) == 0;
|
||||
TagDouble tagDouble = (TagDouble) o;
|
||||
return Double.compare(value, tagDouble.value) == 0;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,12 +1,12 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
public class NBTFloat extends NBTNumber {
|
||||
public class TagFloat extends TagNumber {
|
||||
|
||||
public static byte TYPE_ID = 5;
|
||||
|
||||
private float value;
|
||||
|
||||
public NBTFloat(float value) {
|
||||
public TagFloat(float value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,8 @@ public class NBTFloat extends NBTNumber {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTFloat nbtFloat = (NBTFloat) o;
|
||||
return Float.compare(value, nbtFloat.value) == 0;
|
||||
TagFloat tagFloat = (TagFloat) o;
|
||||
return Float.compare(value, tagFloat.value) == 0;
|
||||
}
|
||||
|
||||
@Override
|
116
src/main/java/com/io/yutian/elementoriginlib/nbt/TagHelper.java
Normal file
116
src/main/java/com/io/yutian/elementoriginlib/nbt/TagHelper.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class TagHelper {
|
||||
|
||||
public static Object tagToJson(Tag tag) {
|
||||
switch (tag.getId()) {
|
||||
case 1: // ByteTag
|
||||
return ((ByteTag) tag).getAsByte();
|
||||
case 2: // ShortTag
|
||||
return ((ShortTag) tag).getAsShort();
|
||||
case 3: // IntTag
|
||||
return ((IntTag) tag).getAsInt();
|
||||
case 4: // LongTag
|
||||
return ((LongTag) tag).getAsLong();
|
||||
case 5: // FloatTag
|
||||
return ((FloatTag) tag).getAsFloat();
|
||||
case 6: // DoubleTag
|
||||
return ((DoubleTag) tag).getAsDouble();
|
||||
case 7: // ByteArrayTag
|
||||
return ((ByteArrayTag) tag).getAsByteArray();
|
||||
case 8: // StringTag
|
||||
return ((StringTag) tag).getAsString();
|
||||
case 9: // ListTag
|
||||
ListTag listTag = (ListTag) tag;
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (Tag element : listTag) {
|
||||
jsonArray.put(tagToJson(element));
|
||||
}
|
||||
return jsonArray;
|
||||
case 10: // CompoundTag
|
||||
CompoundTag compoundTag = (CompoundTag) tag;
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
for (String key : compoundTag.getAllKeys()) {
|
||||
jsonObject.put(key, tagToJson(compoundTag.get(key)));
|
||||
}
|
||||
return jsonObject;
|
||||
case 11:
|
||||
return ((IntArrayTag) tag).getAsIntArray();
|
||||
case 12:
|
||||
return ((LongArrayTag) tag).getAsLongArray();
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported Tag type: " + tag.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public static Tag jsonToTag(Object json) {
|
||||
if (json instanceof JSONObject) {
|
||||
JSONObject jsonObject = (JSONObject) json;
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
for (String key : jsonObject.keySet()) {
|
||||
compoundTag.put(key, jsonToTag(jsonObject.get(key)));
|
||||
}
|
||||
return compoundTag;
|
||||
} else if (json instanceof JSONArray) {
|
||||
JSONArray jsonArray = (JSONArray) json;
|
||||
ListTag listTag = new ListTag();
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
listTag.add(jsonToTag(jsonArray.get(i)));
|
||||
}
|
||||
return listTag;
|
||||
} else if (json instanceof String) {
|
||||
return StringTag.valueOf((String) json);
|
||||
} else if (json instanceof Integer) {
|
||||
return IntTag.valueOf((Integer) json);
|
||||
} else if (json instanceof Long) {
|
||||
return LongTag.valueOf((Long) json);
|
||||
} else if (json instanceof Double) {
|
||||
return DoubleTag.valueOf((Double) json);
|
||||
} else if (json instanceof Float) {
|
||||
return FloatTag.valueOf((Float) json);
|
||||
} else if (json instanceof Byte) {
|
||||
return ByteTag.valueOf((Byte) json);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported JSON type: " + json.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ITag convert(Object object) {
|
||||
if (object instanceof Byte) {
|
||||
return new TagByte((byte) object);
|
||||
} else if (object instanceof Short) {
|
||||
return new TagShort((short) object);
|
||||
} else if (object instanceof Integer) {
|
||||
return new TagInt((int) object);
|
||||
} else if (object instanceof Long) {
|
||||
return new TagLong((long) object);
|
||||
} else if (object instanceof Float) {
|
||||
return new TagFloat((float) object);
|
||||
} else if (object instanceof Double) {
|
||||
return new TagDouble((double) object);
|
||||
} else if (object instanceof byte[]) {
|
||||
return new TagByteArray((byte[]) object);
|
||||
} else if (object instanceof String) {
|
||||
return new TagString((String) object);
|
||||
} else if (object instanceof int[]) {
|
||||
return new TagIntArray((int[]) object);
|
||||
} else if (object instanceof long[]) {
|
||||
return new TagLongArray((long[]) object);
|
||||
} else if (object instanceof Boolean) {
|
||||
return new TagByte((byte) ((boolean)object ? 1 : 0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object convertNMSNBT(ITag nbt) {
|
||||
return ITag.asNMS(nbt);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
public class NBTInt extends NBTNumber {
|
||||
public class TagInt extends TagNumber {
|
||||
|
||||
public static byte TYPE_ID = 3;
|
||||
|
||||
private int value;
|
||||
|
||||
public NBTInt(int value) {
|
||||
public TagInt(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,8 @@ public class NBTInt extends NBTNumber {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTInt nbtInt = (NBTInt) o;
|
||||
return value == nbtInt.value;
|
||||
TagInt tagInt = (TagInt) o;
|
||||
return value == tagInt.value;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -2,13 +2,13 @@ package com.io.yutian.elementoriginlib.nbt;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NBTIntArray implements INBT {
|
||||
public class TagIntArray implements ITag {
|
||||
|
||||
public static byte TYPE_ID = 11;
|
||||
|
||||
private int[] value;
|
||||
|
||||
public NBTIntArray(int[] value) {
|
||||
public TagIntArray(int[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ public class NBTIntArray implements INBT {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTIntArray that = (NBTIntArray) o;
|
||||
TagIntArray that = (TagIntArray) o;
|
||||
return Arrays.equals(value, that.value);
|
||||
}
|
||||
|
|
@ -4,18 +4,18 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class NBTList<T extends INBT> implements INBT {
|
||||
public class TagList<T extends ITag> implements ITag {
|
||||
|
||||
public static byte TYPE_ID = 9;
|
||||
|
||||
private List<T> value = new ArrayList<>();
|
||||
private byte type = 0;
|
||||
|
||||
public NBTList(List<T> value) {
|
||||
public TagList(List<T> value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTList() {
|
||||
public TagList() {
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
|
@ -72,8 +72,8 @@ public class NBTList<T extends INBT> implements INBT {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTList<?> nbtList = (NBTList<?>) o;
|
||||
return type == nbtList.type && Objects.equals(value, nbtList.value);
|
||||
TagList<?> tagList = (TagList<?>) o;
|
||||
return type == tagList.type && Objects.equals(value, tagList.value);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,16 +1,16 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
public class NBTLong extends NBTNumber {
|
||||
public class TagLong extends TagNumber {
|
||||
|
||||
public static byte TYPE_ID = 4;
|
||||
|
||||
private long value;
|
||||
|
||||
public NBTLong(long value) {
|
||||
public TagLong(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTLong() {
|
||||
public TagLong() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,8 +65,8 @@ public class NBTLong extends NBTNumber {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTLong nbtLong = (NBTLong) o;
|
||||
return value == nbtLong.value;
|
||||
TagLong tagLong = (TagLong) o;
|
||||
return value == tagLong.value;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -2,13 +2,13 @@ package com.io.yutian.elementoriginlib.nbt;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NBTLongArray implements INBT {
|
||||
public class TagLongArray implements ITag {
|
||||
|
||||
public static byte TYPE_ID = 12;
|
||||
|
||||
private long[] value;
|
||||
|
||||
public NBTLongArray(long[] value) {
|
||||
public TagLongArray(long[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ public class NBTLongArray implements INBT {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTLongArray that = (NBTLongArray) o;
|
||||
TagLongArray that = (TagLongArray) o;
|
||||
return Arrays.equals(value, that.value);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
public abstract class NBTNumber implements INBT {
|
||||
public abstract class TagNumber implements ITag {
|
||||
|
||||
public abstract long getLong();
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
package com.io.yutian.elementoriginlib.nbt;
|
||||
|
||||
public class NBTShort extends NBTNumber {
|
||||
public class TagShort extends TagNumber {
|
||||
|
||||
public static byte TYPE_ID = 2;
|
||||
|
||||
private short value;
|
||||
|
||||
public NBTShort(short value) {
|
||||
public TagShort(short value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTShort() {
|
||||
public TagShort() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,7 +58,7 @@ public class NBTShort extends NBTNumber {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTShort nbtShort = (NBTShort) o;
|
||||
TagShort nbtShort = (TagShort) o;
|
||||
return value == nbtShort.value;
|
||||
}
|
||||
|
|
@ -2,17 +2,17 @@ package com.io.yutian.elementoriginlib.nbt;
|
|||
|
||||
import java.util.Objects;
|
||||
|
||||
public class NBTString implements INBT {
|
||||
public class TagString implements ITag {
|
||||
|
||||
public static byte TYPE_ID = 8;
|
||||
|
||||
private String value;
|
||||
|
||||
public NBTString(String value) {
|
||||
public TagString(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTString() {
|
||||
public TagString() {
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
|
@ -34,8 +34,8 @@ public class NBTString implements INBT {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
NBTString nbtString = (NBTString) o;
|
||||
return Objects.equals(value, nbtString.value);
|
||||
TagString tagString = (TagString) o;
|
||||
return Objects.equals(value, tagString.value);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,7 @@
|
|||
package com.io.yutian.elementoriginlib.point;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
@ -11,7 +13,8 @@ public class DirectionPoint extends Point {
|
|||
private float yaw;
|
||||
private float pitch;
|
||||
|
||||
public DirectionPoint(int x, int y, int z, float yaw, float pitch) {
|
||||
@JsonCreator
|
||||
public DirectionPoint(@JsonProperty("x") int x, @JsonProperty("y") int y, @JsonProperty("z") int z, @JsonProperty("yaw") float yaw, @JsonProperty("pitch") float pitch) {
|
||||
super(x, y, z);
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.io.yutian.elementoriginlib.point;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
@ -12,7 +13,7 @@ public class Point {
|
|||
private double y;
|
||||
private double z;
|
||||
|
||||
public Point(int x, int y, int z) {
|
||||
public Point(@JsonProperty("x") int x, @JsonProperty("y") int y, @JsonProperty("z") int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.io.yutian.elementoriginlib.point;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.redis;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
public interface IJedisGetter {
|
||||
|
||||
Jedis getRedis();
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.redis;
|
||||
|
||||
import com.io.yutian.elementoriginlib.ElementOriginLib;
|
||||
import com.io.yutian.elementoriginlib.util.Pair;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RedisCacheSyncTimer {
|
||||
|
||||
private static final String LOCK_KEY = "sync_lock";
|
||||
private static final int LOCK_EXPIRE_SECONDS = 290;
|
||||
private final Map<Plugin, PluginInfo> pluginInfos = new HashMap<>();
|
||||
|
||||
private BukkitTask task;
|
||||
|
||||
public RedisCacheSyncTimer() {
|
||||
task = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (pluginInfos.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<Plugin, PluginInfo> entry : pluginInfos.entrySet()) {
|
||||
Plugin plugin = entry.getKey();
|
||||
if (!plugin.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
PluginInfo pluginInfo = entry.getValue();
|
||||
String lockKey = LOCK_KEY + "_" + plugin.getName();
|
||||
IJedisGetter jedisGetter = pluginInfo.getJedisGetter();
|
||||
try (Jedis jedis = jedisGetter.getRedis()) {
|
||||
long lockResult = jedis.setnx(lockKey, "locked");
|
||||
if (lockResult != 1) {
|
||||
continue;
|
||||
}
|
||||
jedis.expire(lockKey, LOCK_EXPIRE_SECONDS);
|
||||
for (Map.Entry<Pair<String, String>, RedisCacheSynchronizer> entry1 : entry.getValue().getSynchronizers().entrySet()) {
|
||||
Pair<String, String> key = entry1.getKey();
|
||||
RedisCacheSynchronizer synchronizer = entry1.getValue();
|
||||
String k1 = key.first();
|
||||
String k2 = key.second();
|
||||
for (String k : jedis.keys(k1+":*")) {
|
||||
String data = null;
|
||||
if (k2 == null) {
|
||||
data = jedis.get(k);
|
||||
} else {
|
||||
data = jedis.hget(k, k2);
|
||||
}
|
||||
if (data != null) {
|
||||
String finalData = data;
|
||||
synchronizer.sync(k, finalData);
|
||||
if (k2 == null) {
|
||||
jedis.del(k);
|
||||
} else {
|
||||
jedis.hdel(k, k2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskTimerAsynchronously(ElementOriginLib.inst(), 1200L, 5 * 60 * 20L);
|
||||
}
|
||||
|
||||
public void registerSynchronizer(Plugin plugin, IJedisGetter jedisGetter, Pair<String, String> key, RedisCacheSynchronizer synchronizer) {
|
||||
PluginInfo pluginInfo = pluginInfos.computeIfAbsent(plugin, k -> new PluginInfo(jedisGetter));
|
||||
pluginInfo.addSynchronizer(key, synchronizer);
|
||||
pluginInfos.put(plugin, pluginInfo);
|
||||
}
|
||||
|
||||
class PluginInfo {
|
||||
|
||||
private IJedisGetter jedisGetter;
|
||||
private Map<Pair<String, String>, RedisCacheSynchronizer> synchronizers;
|
||||
|
||||
public PluginInfo(IJedisGetter jedisGetter) {
|
||||
this.jedisGetter = jedisGetter;
|
||||
this.synchronizers = new HashMap<>();
|
||||
}
|
||||
|
||||
public void addSynchronizer(Pair<String, String> key, RedisCacheSynchronizer synchronizer) {
|
||||
if (key == null || synchronizer == null) {
|
||||
return;
|
||||
}
|
||||
if (synchronizers.containsKey(key)) {
|
||||
throw new IllegalArgumentException("Key already registered: " + key);
|
||||
}
|
||||
synchronizers.put(key, synchronizer);
|
||||
}
|
||||
|
||||
public IJedisGetter getJedisGetter() {
|
||||
return jedisGetter;
|
||||
}
|
||||
|
||||
public Map<Pair<String, String>, RedisCacheSynchronizer> getSynchronizers() {
|
||||
return synchronizers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.redis;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RedisCacheSynchronizer {
|
||||
|
||||
void sync(String key, String data);
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@ import java.io.File;
|
|||
import java.time.Duration;
|
||||
import java.util.Set;
|
||||
|
||||
public class RedisIO implements IJedisGetter {
|
||||
public class RedisIO {
|
||||
|
||||
private JedisPool jedisPool;
|
||||
|
||||
|
@ -80,8 +80,4 @@ public class RedisIO implements IJedisGetter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jedis getRedis() {
|
||||
return jedisPool.getResource();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.serialize;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public interface ISerializable<T> {
|
||||
|
||||
JSONObject serialize();
|
||||
|
||||
T deserialize(JSONObject jsonObject);
|
||||
|
||||
}
|
|
@ -1,189 +1,59 @@
|
|||
package com.io.yutian.elementoriginlib.serialize;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.SerializeException;
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.io.yutian.elementoriginlib.serialize.serializers.ItemStackDeserializer;
|
||||
import com.io.yutian.elementoriginlib.serialize.serializers.ItemStackSerializer;
|
||||
import com.io.yutian.elementoriginlib.serialize.serializers.UUIDDeserializer;
|
||||
import com.io.yutian.elementoriginlib.serialize.serializers.UUIDSerializer;
|
||||
import com.io.yutian.elementoriginlib.util.ReflectionUtil;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SerializeHelper {
|
||||
|
||||
private static Map<Class<?>, Serializer> serializers = new HashMap<>();
|
||||
|
||||
public static <T, V> void registerSerializer(Class<T> clazz, Serializer<T> serializer) {
|
||||
serializers.put(clazz, serializer);
|
||||
}
|
||||
|
||||
public static <T> JSONObject serialize(T obj) throws SerializeException {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
Class clazz = obj.getClass();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
if (field.isAnnotationPresent(SerializeIgnore.class)) {
|
||||
continue;
|
||||
}
|
||||
Object value = field.get(obj);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
Object serializeValue = serializeValue(value);
|
||||
jsonObject.put(field.getName(), serializeValue);
|
||||
}
|
||||
return jsonObject;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new SerializeException(obj.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T deserialize(Class<T> clazz, JSONObject jsonObject) throws SerializeException {
|
||||
try {
|
||||
Unsafe unsafe = ReflectionUtil.getUnsafe();
|
||||
T instance = (T) unsafe.allocateInstance(clazz);
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
if (field.isAnnotationPresent(SerializeIgnore.class)) {
|
||||
continue;
|
||||
}
|
||||
String name = field.getName();
|
||||
if (name.equalsIgnoreCase("this$0")) {
|
||||
continue;
|
||||
}
|
||||
if (!jsonObject.has(name)) {
|
||||
continue;
|
||||
}
|
||||
Object value = jsonObject.get(name);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
Object deserializeValue = deserializeValue(field, field.getType(), value);
|
||||
ReflectionUtil.setFieldUsingUnsafe(field, instance, deserializeValue);
|
||||
}
|
||||
return instance;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new SerializeException(clazz, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object deserializeValue(Field field, Class clazz0, Object value) throws SerializeException {
|
||||
Class clazz = clazz0;
|
||||
if (WRAPPER_TO_PRIMITIVE.containsKey(clazz)) {
|
||||
clazz = WRAPPER_TO_PRIMITIVE.get(clazz);
|
||||
}
|
||||
if (serializers.containsKey(clazz)) {
|
||||
Serializer serializer = serializers.get(clazz);
|
||||
return serializer.deserialize(value);
|
||||
}
|
||||
if (ISerializable.class.isAssignableFrom(clazz)) {
|
||||
ISerializable iSerializable = (ISerializable) value;
|
||||
JSONObject jsonObject = (JSONObject) value;
|
||||
return iSerializable.deserialize(jsonObject);
|
||||
} else if (clazz.isPrimitive() || clazz.equals(String.class)) {
|
||||
return value;
|
||||
} else if (clazz.isEnum()) {
|
||||
return Enum.valueOf((Class<Enum>) clazz, (String) value);
|
||||
} else if (clazz.isArray()) {
|
||||
JSONArray jsonArray = (JSONArray) value;
|
||||
int length = jsonArray.length();
|
||||
Object object = Array.newInstance(clazz.getComponentType(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Array.set(object, i, deserializeValue(field, clazz.getComponentType(), jsonArray.get(i)));
|
||||
}
|
||||
return object;
|
||||
} else if (List.class.isAssignableFrom(clazz)) {
|
||||
List list = new ArrayList();
|
||||
JSONArray jsonArray = (JSONArray) value;
|
||||
Type genericType = field.getGenericType();
|
||||
Class<?> elementType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
list.add(deserializeValue(field, elementType, jsonArray.get(i)));
|
||||
}
|
||||
return list;
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
Map map = new HashMap();
|
||||
Type genericType = field.getGenericType();
|
||||
Class<?> valueType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[1];
|
||||
JSONObject jsonObject = (JSONObject) value;
|
||||
for (String key : jsonObject.keySet()) {
|
||||
map.put(key, deserializeValue(field, valueType, jsonObject.get(key)));
|
||||
}
|
||||
return map;
|
||||
} else {
|
||||
return deserialize(clazz, (JSONObject) value);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object serializeValue(Object value) throws SerializeException {
|
||||
Class clazz = value.getClass();
|
||||
if (WRAPPER_TO_PRIMITIVE.containsKey(clazz)) {
|
||||
clazz = WRAPPER_TO_PRIMITIVE.get(clazz);
|
||||
}
|
||||
if (serializers.containsKey(clazz)) {
|
||||
Serializer serializer = serializers.get(clazz);
|
||||
return serializer.serialize(value);
|
||||
}
|
||||
if (ISerializable.class.isAssignableFrom(clazz)) {
|
||||
ISerializable iSerializable = (ISerializable) value;
|
||||
return iSerializable.serialize();
|
||||
} else if (clazz.isPrimitive() || clazz.equals(String.class)) {
|
||||
return value;
|
||||
} else if (clazz.isEnum()) {
|
||||
return ((Enum) value).name();
|
||||
} else if (clazz.isArray()) {
|
||||
Class elementType = clazz.getComponentType();
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
int length = Array.getLength(value);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object element = Array.get(value, i);
|
||||
jsonArray.put(serializeValue(element));
|
||||
}
|
||||
return jsonArray;
|
||||
} else if (List.class.isAssignableFrom(clazz)) {
|
||||
List list = (List) value;
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (Object element : list) {
|
||||
jsonArray.put(serializeValue(element));
|
||||
}
|
||||
return jsonArray;
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
Map map = (Map) value;
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
for (Object key : map.keySet()) {
|
||||
jsonObject.put(key.toString(), serializeValue(map.get(key)));
|
||||
}
|
||||
return jsonObject;
|
||||
} else {
|
||||
return serialize(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE = new HashMap<>();
|
||||
private static final ObjectMapper objectMapper;
|
||||
|
||||
static {
|
||||
WRAPPER_TO_PRIMITIVE.put(Boolean.class, boolean.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(Byte.class, byte.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(Short.class, short.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(Character.class, char.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(Integer.class, int.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(Long.class, long.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(Float.class, float.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(Double.class, double.class);
|
||||
WRAPPER_TO_PRIMITIVE.put(CraftItemStack.class, ItemStack.class);
|
||||
objectMapper = new ObjectMapper();
|
||||
|
||||
registerSerializer(UUID.class, new UUIDSerializer());
|
||||
registerSerializer(ItemStack.class, new ItemStackSerializer());
|
||||
objectMapper.setVisibility(
|
||||
VisibilityChecker.Std.defaultInstance()
|
||||
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
|
||||
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
);
|
||||
|
||||
SimpleModule module = new SimpleModule();
|
||||
module.addSerializer(UUID.class, new UUIDSerializer());
|
||||
module.addDeserializer(UUID.class, new UUIDDeserializer());
|
||||
|
||||
module.addSerializer(ItemStack.class, new ItemStackSerializer());
|
||||
module.addDeserializer(ItemStack.class, new ItemStackDeserializer());
|
||||
objectMapper.registerModule(module);
|
||||
|
||||
}
|
||||
|
||||
public static String serialize(Object obj) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException("Failed to serialize object: " + obj, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T deserialize(String json, Class<T> clazz) {
|
||||
try {
|
||||
return objectMapper.readValue(json, clazz);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException("Failed to deserialize JSON: " + json, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.serialize;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SerializeIgnore {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.serialize;
|
||||
|
||||
public interface Serializer<T> {
|
||||
|
||||
Object serialize(T value);
|
||||
|
||||
T deserialize(Object value);
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.io.yutian.elementoriginlib.serialize.serializers;
|
||||
|
||||
import com.fasterxml.jackson.core.JacksonException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagHelper;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ItemStackDeserializer extends JsonDeserializer<ItemStack> {
|
||||
|
||||
@Override
|
||||
public ItemStack deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
|
||||
CompoundTag compoundTag = (CompoundTag) TagHelper.jsonToTag(new JSONObject(jsonParser.readValueAsTree().toString()));
|
||||
net.minecraft.world.item.ItemStack nmsItemStack = net.minecraft.world.item.ItemStack.parse(getRegistry(), compoundTag).get();
|
||||
return CraftItemStack.asCraftMirror(nmsItemStack);
|
||||
}
|
||||
|
||||
public static HolderLookup.Provider getRegistry() {
|
||||
MinecraftServer minecraftServer = MinecraftServer.getServer();
|
||||
return minecraftServer.registryAccess();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,95 +1,20 @@
|
|||
package com.io.yutian.elementoriginlib.serialize.serializers;
|
||||
|
||||
import com.io.yutian.elementoriginlib.serialize.Serializer;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.nbt.*;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagHelper;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class ItemStackSerializer implements Serializer<ItemStack> {
|
||||
import java.io.IOException;
|
||||
|
||||
public class ItemStackSerializer extends JsonSerializer<ItemStack> {
|
||||
|
||||
@Override
|
||||
public Object serialize(ItemStack value) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
public void serialize(ItemStack value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(value);
|
||||
jsonObject.put("id", nmsItemStack.c().d().j().g());
|
||||
jsonObject.put("Count", nmsItemStack.J());
|
||||
NBTTagCompound nbtTagCompound = nmsItemStack.w();
|
||||
JSONObject tagJsonObject = new JSONObject();
|
||||
for (String key : nbtTagCompound.e()) {
|
||||
NBTBase nbtBase = nbtTagCompound.c(key);
|
||||
tagJsonObject.put(key, serializeNBT(nbtBase));
|
||||
}
|
||||
jsonObject.put("tag", tagJsonObject);
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
private Object serializeNBT(NBTBase nbtBase) {
|
||||
byte type = nbtBase.b();
|
||||
switch (type) {
|
||||
case 1:
|
||||
NBTTagByte nbtTagByte = (NBTTagByte) nbtBase;
|
||||
return nbtTagByte.i();
|
||||
case 2:
|
||||
NBTTagShort nbtTagShort = (NBTTagShort) nbtBase;
|
||||
return nbtTagShort.h();
|
||||
case 3:
|
||||
NBTTagInt nbtTagInt = (NBTTagInt) nbtBase;
|
||||
return nbtTagInt.g();
|
||||
case 4:
|
||||
NBTTagLong nbtTagLong = (NBTTagLong) nbtBase;
|
||||
return nbtTagLong.f();
|
||||
case 5:
|
||||
NBTTagFloat nbtTagFloat = (NBTTagFloat) nbtBase;
|
||||
return nbtTagFloat.k();
|
||||
case 6:
|
||||
NBTTagDouble nbtTagDouble = (NBTTagDouble) nbtBase;
|
||||
return nbtTagDouble.j();
|
||||
case 7:
|
||||
NBTTagByteArray tagByteArray = (NBTTagByteArray) nbtBase;
|
||||
return tagByteArray.e();
|
||||
case 8:
|
||||
NBTTagString nbtTagString = (NBTTagString) nbtBase;
|
||||
return nbtTagString.t_();
|
||||
case 9:
|
||||
NBTTagList nbtTagList = (NBTTagList) nbtBase;
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (net.minecraft.nbt.NBTBase base : nbtTagList) {
|
||||
jsonArray.put(serializeNBT(base));
|
||||
}
|
||||
return jsonArray;
|
||||
case 10:
|
||||
NBTTagCompound nbtTagCompound = (NBTTagCompound) nbtBase;
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
for (String key : nbtTagCompound.e()) {
|
||||
jsonObject.put(key, serializeNBT(nbtTagCompound.c(key)));
|
||||
}
|
||||
return jsonObject;
|
||||
case 11:
|
||||
NBTTagIntArray nbtTagIntArray = (NBTTagIntArray) nbtBase;
|
||||
return nbtTagIntArray.g();
|
||||
case 12:
|
||||
NBTTagLongArray nbtTagLongArray = (NBTTagLongArray) nbtBase;
|
||||
return nbtTagLongArray.g();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack deserialize(Object value) {
|
||||
JSONObject jsonObject = (JSONObject) value;
|
||||
String arg = jsonObject.toString();
|
||||
NBTTagCompound nbtTagCompound;
|
||||
try {
|
||||
nbtTagCompound = net.minecraft.nbt.MojangsonParser.a(arg);
|
||||
} catch (CommandSyntaxException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
net.minecraft.world.item.ItemStack nmsItemStack = net.minecraft.world.item.ItemStack.a(nbtTagCompound);
|
||||
return CraftItemStack.asCraftMirror(nmsItemStack);
|
||||
gen.writeRawValue(TagHelper.tagToJson(nmsItemStack.save(ItemStackDeserializer.getRegistry())).toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.io.yutian.elementoriginlib.serialize.serializers;
|
||||
|
||||
import com.fasterxml.jackson.core.JacksonException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UUIDDeserializer extends JsonDeserializer<UUID> {
|
||||
@Override
|
||||
public UUID deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
|
||||
return UUID.fromString(jsonParser.getText());
|
||||
}
|
||||
}
|
|
@ -1,17 +1,15 @@
|
|||
package com.io.yutian.elementoriginlib.serialize.serializers;
|
||||
|
||||
import com.io.yutian.elementoriginlib.serialize.Serializer;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UUIDSerializer implements Serializer<UUID> {
|
||||
public class UUIDSerializer extends JsonSerializer<UUID> {
|
||||
@Override
|
||||
public Object serialize(UUID value) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID deserialize(Object value) {
|
||||
return UUID.fromString((String) value);
|
||||
public void serialize(UUID uuid, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
|
||||
jsonGenerator.writeString(uuid.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLManager;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLQuery;
|
||||
import com.io.yutian.elementoriginlib.sql.api.util.TimeDateUtils;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class SQLHelper {
|
||||
|
||||
public static SQLManagerImpl createManager(
|
||||
@NotNull String driver, @NotNull String url,
|
||||
@NotNull String username, @Nullable String password) {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setDriverClassName(driver);
|
||||
config.setJdbcUrl(url);
|
||||
config.setUsername(username);
|
||||
config.setPassword(password);
|
||||
return createManager(config);
|
||||
}
|
||||
|
||||
public static SQLManagerImpl createManager(@NotNull Properties properties) {
|
||||
return createManager(new HikariConfig(properties));
|
||||
}
|
||||
|
||||
public static SQLManagerImpl createManager(@NotNull HikariConfig config) {
|
||||
return new SQLManagerImpl(new HikariDataSource(config));
|
||||
}
|
||||
|
||||
public static void shutdownManager(SQLManager manager, boolean forceClose, boolean outputActiveQuery) {
|
||||
if (!manager.getActiveQuery().isEmpty()) {
|
||||
manager.getLogger().warn("There are " + manager.getActiveQuery().size() + " connections still running");
|
||||
for (SQLQuery value : manager.getActiveQuery().values()) {
|
||||
if (outputActiveQuery) {
|
||||
manager.getLogger().warn(String.format("#%s -> %s", value.getAction().getShortID(), value.getSQLContent()));
|
||||
manager.getLogger().warn(String.format("- execute at %s", TimeDateUtils.getTimeString(value.getExecuteTime())));
|
||||
}
|
||||
if (forceClose) value.close();
|
||||
}
|
||||
}
|
||||
if (manager.getDataSource() instanceof HikariDataSource) {
|
||||
//Close hikari pool
|
||||
((HikariDataSource) manager.getDataSource()).close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void shutdownManager(SQLManager manager) {
|
||||
shutdownManager(manager, true, manager.isDebugMode());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLExceptionHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class AbstractSQLAction<T> implements SQLAction<T> {
|
||||
|
||||
protected final @NotNull String sqlContent;
|
||||
private final @NotNull SQLManagerImpl sqlManager;
|
||||
private final @NotNull UUID uuid;
|
||||
private final long createNanoTime;
|
||||
|
||||
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql) {
|
||||
this(manager, sql, System.nanoTime());
|
||||
}
|
||||
|
||||
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, @NotNull UUID uuid) {
|
||||
this(manager, sql, uuid, System.nanoTime());
|
||||
}
|
||||
|
||||
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, long createNanoTime) {
|
||||
this(manager, sql, UUID.randomUUID(), createNanoTime);
|
||||
}
|
||||
|
||||
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql,
|
||||
@NotNull UUID uuid, long createNanoTime) {
|
||||
Objects.requireNonNull(manager);
|
||||
Objects.requireNonNull(sql);
|
||||
Objects.requireNonNull(uuid);
|
||||
this.sqlManager = manager;
|
||||
this.sqlContent = sql;
|
||||
this.uuid = uuid;
|
||||
this.createNanoTime = createNanoTime;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull UUID getActionUUID() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getShortID() {
|
||||
return getActionUUID().toString().substring(0, 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCreateTime(TimeUnit unit) {
|
||||
return unit.convert(createNanoTime, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getSQLContent() {
|
||||
return this.sqlContent.trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SQLManagerImpl getManager() {
|
||||
return this.sqlManager;
|
||||
}
|
||||
|
||||
protected void debugMessage(List<Object[]> params) {
|
||||
if (getManager().isDebugMode()) {
|
||||
try {
|
||||
getManager().getDebugHandler().beforeExecute(this, params);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("FutureReturnValueIgnored")
|
||||
public void executeAsync(SQLHandler<T> success, SQLExceptionHandler failure) {
|
||||
getManager().getExecutorPool().submit(() -> {
|
||||
try {
|
||||
T returnedValue = execute();
|
||||
if (success != null) success.accept(returnedValue);
|
||||
} catch (SQLException e) {
|
||||
handleException(failure, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull <R> CompletableFuture<R> executeFuture(@NotNull SQLFunction<T, R> handler) {
|
||||
CompletableFuture<R> future = new CompletableFuture<>();
|
||||
executeAsync((t -> future.complete(handler.apply(t))), (e, q) -> future.completeExceptionally(e));
|
||||
return future;
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.util.StatementUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PreparedSQLBatchUpdateActionImpl<T extends Number>
|
||||
extends AbstractSQLAction<List<T>>
|
||||
implements PreparedSQLUpdateBatchAction<T> {
|
||||
|
||||
boolean returnKeys = false;
|
||||
@NotNull List<Object[]> allParams = new ArrayList<>();
|
||||
|
||||
protected final @NotNull Class<T> numberClass;
|
||||
|
||||
public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull String sql) {
|
||||
super(manager, sql);
|
||||
this.numberClass = numberClass;
|
||||
this.allParams = new ArrayList<>();
|
||||
}
|
||||
|
||||
public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull UUID uuid, @NotNull String sql) {
|
||||
super(manager, sql, uuid);
|
||||
this.numberClass = numberClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedSQLBatchUpdateActionImpl<T> setAllParams(Iterable<Object[]> allParams) {
|
||||
List<Object[]> paramsList = new ArrayList<>();
|
||||
allParams.forEach(paramsList::add);
|
||||
this.allParams = paramsList;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedSQLBatchUpdateActionImpl<T> addParamsBatch(Object... params) {
|
||||
this.allParams.add(params);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedSQLBatchUpdateActionImpl<T> returnGeneratedKeys() {
|
||||
this.returnKeys = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> PreparedSQLBatchUpdateActionImpl<N> returnGeneratedKeys(Class<N> keyTypeClass) {
|
||||
return new PreparedSQLBatchUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent())
|
||||
.setAllParams(allParams).returnGeneratedKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<T> execute() throws SQLException {
|
||||
debugMessage(allParams);
|
||||
|
||||
try (Connection connection = getManager().getConnection()) {
|
||||
try (PreparedStatement statement = StatementUtil.createPrepareStatementBatch(
|
||||
connection, getSQLContent(), allParams, returnKeys
|
||||
)) {
|
||||
int[] executed = statement.executeBatch();
|
||||
|
||||
if (!returnKeys) {
|
||||
return Arrays.stream(executed).mapToObj(numberClass::cast).collect(Collectors.toList());
|
||||
} else {
|
||||
try (ResultSet resultSet = statement.getGeneratedKeys()) {
|
||||
List<T> generatedKeys = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
generatedKeys.add(resultSet.getObject(1, numberClass));
|
||||
}
|
||||
return generatedKeys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.util.StatementUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PreparedSQLUpdateActionImpl<T extends Number>
|
||||
extends SQLUpdateActionImpl<T>
|
||||
implements PreparedSQLUpdateAction<T> {
|
||||
|
||||
Object[] params;
|
||||
|
||||
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull String sql) {
|
||||
this(manager, numberClass, sql, (Object[]) null);
|
||||
}
|
||||
|
||||
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull String sql, @Nullable List<Object> params) {
|
||||
this(manager, numberClass, sql, params == null ? null : params.toArray());
|
||||
}
|
||||
|
||||
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull String sql, @Nullable Object[] params) {
|
||||
super(manager, numberClass, sql);
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull UUID uuid, @NotNull String sql,
|
||||
Object[] params) {
|
||||
super(manager, numberClass, uuid, sql);
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedSQLUpdateActionImpl<T> setParams(Object... params) {
|
||||
this.params = params;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedSQLUpdateActionImpl<T> setParams(@Nullable Iterable<Object> params) {
|
||||
if (params == null) {
|
||||
return setParams((Object[]) null);
|
||||
} else {
|
||||
List<Object> paramsList = new ArrayList<>();
|
||||
params.forEach(paramsList::add);
|
||||
return setParams(paramsList.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull T execute() throws SQLException {
|
||||
debugMessage(Collections.singletonList(params));
|
||||
|
||||
try (Connection connection = getManager().getConnection()) {
|
||||
|
||||
try (PreparedStatement statement = StatementUtil.createPrepareStatement(
|
||||
connection, getSQLContent(), params, returnGeneratedKeys
|
||||
)) {
|
||||
|
||||
int changes = statement.executeUpdate();
|
||||
if (!returnGeneratedKeys) return numberClass.cast(changes);
|
||||
else {
|
||||
try (ResultSet resultSet = statement.getGeneratedKeys()) {
|
||||
return resultSet.next() ? resultSet.getObject(1, numberClass) : numberClass.cast(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> SQLUpdateAction<N> returnGeneratedKey(Class<N> keyTypeClass) {
|
||||
PreparedSQLUpdateActionImpl<N> newAction = new PreparedSQLUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent(), params);
|
||||
newAction.returnGeneratedKey();
|
||||
return newAction;
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SQLUpdateActionImpl<T extends Number>
|
||||
extends AbstractSQLAction<T>
|
||||
implements SQLUpdateAction<T> {
|
||||
|
||||
protected final @NotNull Class<T> numberClass;
|
||||
|
||||
protected boolean returnGeneratedKeys = false;
|
||||
|
||||
public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull String sql) {
|
||||
super(manager, sql);
|
||||
this.numberClass = numberClass;
|
||||
}
|
||||
|
||||
public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
|
||||
@NotNull UUID uuid, @NotNull String sql) {
|
||||
super(manager, sql, uuid);
|
||||
this.numberClass = numberClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull T execute() throws SQLException {
|
||||
debugMessage(new ArrayList<>());
|
||||
|
||||
try (Connection connection = getManager().getConnection()) {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
|
||||
if (!returnGeneratedKeys) {
|
||||
return numberClass.cast(statement.executeUpdate(getSQLContent()));
|
||||
} else {
|
||||
statement.executeUpdate(getSQLContent(), Statement.RETURN_GENERATED_KEYS);
|
||||
|
||||
try (ResultSet resultSet = statement.getGeneratedKeys()) {
|
||||
return resultSet.next() ? resultSet.getObject(1, numberClass) : numberClass.cast(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLUpdateAction<T> returnGeneratedKey() {
|
||||
this.returnGeneratedKeys = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> SQLUpdateAction<N> returnGeneratedKey(Class<N> keyTypeClass) {
|
||||
return new SQLUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent()).returnGeneratedKey();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateBatchAction;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SQLUpdateBatchActionImpl
|
||||
extends AbstractSQLAction<List<Integer>>
|
||||
implements SQLUpdateBatchAction {
|
||||
|
||||
protected final List<String> sqlContents = new ArrayList<>();
|
||||
|
||||
public SQLUpdateBatchActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
|
||||
super(manager, sql);
|
||||
this.sqlContents.add(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getSQLContents() {
|
||||
return this.sqlContents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLUpdateBatchAction addBatch(@NotNull String sql) {
|
||||
Objects.requireNonNull(sql, "sql could not be null");
|
||||
this.sqlContents.add(sql);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<Integer> execute() throws SQLException {
|
||||
debugMessage(new ArrayList<>());
|
||||
|
||||
try (Connection connection = getManager().getConnection()) {
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
|
||||
for (String content : this.sqlContents) {
|
||||
statement.addBatch(content);
|
||||
}
|
||||
|
||||
int[] executed = statement.executeBatch();
|
||||
|
||||
return Arrays.stream(executed).boxed().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action.query;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.PreparedQueryAction;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.util.StatementUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PreparedQueryActionImpl extends QueryActionImpl implements PreparedQueryAction {
|
||||
|
||||
Consumer<PreparedStatement> handler;
|
||||
Object[] params;
|
||||
|
||||
public PreparedQueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
|
||||
super(manager, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedQueryActionImpl setParams(@Nullable Object... params) {
|
||||
this.params = params;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedQueryActionImpl setParams(@Nullable Iterable<Object> params) {
|
||||
if (params == null) {
|
||||
return setParams((Object[]) null);
|
||||
} else {
|
||||
List<Object> paramsList = new ArrayList<>();
|
||||
params.forEach(paramsList::add);
|
||||
return setParams(paramsList.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedQueryActionImpl handleStatement(@Nullable Consumer<PreparedStatement> statement) {
|
||||
this.handler = statement;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull SQLQueryImpl execute() throws SQLException {
|
||||
debugMessage(Collections.singletonList(params));
|
||||
|
||||
Connection connection = getManager().getConnection();
|
||||
PreparedStatement preparedStatement;
|
||||
try {
|
||||
if (handler == null) {
|
||||
preparedStatement = StatementUtil.createPrepareStatement(connection, getSQLContent(), this.params);
|
||||
} else {
|
||||
preparedStatement = connection.prepareStatement(getSQLContent());
|
||||
handler.accept(preparedStatement);
|
||||
}
|
||||
} catch (SQLException exception) {
|
||||
connection.close();
|
||||
throw exception;
|
||||
}
|
||||
|
||||
try {
|
||||
SQLQueryImpl query = new SQLQueryImpl(
|
||||
getManager(), this,
|
||||
connection, preparedStatement,
|
||||
preparedStatement.executeQuery()
|
||||
);
|
||||
getManager().getActiveQuery().put(getActionUUID(), query);
|
||||
return query;
|
||||
} catch (SQLException exception) {
|
||||
preparedStatement.close();
|
||||
connection.close();
|
||||
throw exception;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action.query;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.AbstractSQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLQuery;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.QueryAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLExceptionHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class QueryActionImpl extends AbstractSQLAction<SQLQuery> implements QueryAction {
|
||||
|
||||
public QueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
|
||||
super(manager, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SQLQueryImpl execute() throws SQLException {
|
||||
debugMessage(new ArrayList<>());
|
||||
|
||||
Connection connection = getManager().getConnection();
|
||||
Statement statement;
|
||||
|
||||
try {
|
||||
statement = connection.createStatement();
|
||||
} catch (SQLException ex) {
|
||||
connection.close();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
try {
|
||||
SQLQueryImpl query = new SQLQueryImpl(
|
||||
getManager(), this,
|
||||
connection, statement,
|
||||
statement.executeQuery(getSQLContent())
|
||||
);
|
||||
getManager().getActiveQuery().put(getActionUUID(), query);
|
||||
|
||||
return query;
|
||||
} catch (SQLException exception) {
|
||||
statement.close();
|
||||
connection.close();
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void executeAsync(SQLHandler<SQLQuery> success, SQLExceptionHandler failure) {
|
||||
getManager().getExecutorPool().submit(() -> {
|
||||
try (SQLQueryImpl query = execute()) {
|
||||
if (success != null) success.accept(query);
|
||||
} catch (SQLException exception) {
|
||||
handleException(failure, exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.action.query;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLQuery;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SQLQueryImpl implements SQLQuery {
|
||||
|
||||
protected final long executeTime;
|
||||
|
||||
protected final SQLManagerImpl sqlManager;
|
||||
protected final Connection connection;
|
||||
protected final Statement statement;
|
||||
protected final ResultSet resultSet;
|
||||
protected QueryActionImpl queryAction;
|
||||
|
||||
public SQLQueryImpl(
|
||||
SQLManagerImpl sqlManager, QueryActionImpl queryAction,
|
||||
Connection connection, Statement statement, ResultSet resultSet
|
||||
) {
|
||||
this(sqlManager, queryAction, connection, statement, resultSet, System.nanoTime());
|
||||
}
|
||||
|
||||
public SQLQueryImpl(
|
||||
SQLManagerImpl sqlManager, QueryActionImpl queryAction,
|
||||
Connection connection, Statement statement, ResultSet resultSet,
|
||||
long executeTime
|
||||
) {
|
||||
this.executeTime = executeTime;
|
||||
this.sqlManager = sqlManager;
|
||||
this.queryAction = queryAction;
|
||||
this.connection = connection;
|
||||
this.statement = statement;
|
||||
this.resultSet = resultSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExecuteTime(TimeUnit timeUnit) {
|
||||
return timeUnit.convert(this.executeTime, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLManagerImpl getManager() {
|
||||
return this.sqlManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryActionImpl getAction() {
|
||||
return this.queryAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet getResultSet() {
|
||||
return this.resultSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLContent() {
|
||||
return getAction().getSQLContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
if (getResultSet() != null && !getResultSet().isClosed()) getResultSet().close();
|
||||
if (getStatement() != null && !getStatement().isClosed()) getStatement().close();
|
||||
if (getConnection() != null && !getConnection().isClosed()) getConnection().close();
|
||||
|
||||
if (getManager().isDebugMode()) {
|
||||
try {
|
||||
getManager().getDebugHandler().afterQuery(this, getExecuteTime(TimeUnit.NANOSECONDS), System.nanoTime());
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
getManager().getActiveQuery().remove(getAction().getActionUUID());
|
||||
} catch (SQLException e) {
|
||||
getAction().handleException(getAction().defaultExceptionHandler(), e);
|
||||
}
|
||||
this.queryAction = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement getStatement() {
|
||||
return this.statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
return this.connection;
|
||||
}
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLExceptionHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLHandler;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* SQLAction 是用于承载SQL语句并进行处理、返回的基本类。
|
||||
*
|
||||
* <ul>
|
||||
* <li>同步执行 {@link #execute()}, {@link #execute(SQLFunction, SQLExceptionHandler)}
|
||||
* <br>同步执行方法中有会抛出异常的方法与不抛出异常的方法,
|
||||
* <br>若选择不抛出异常,则返回值可能为空,需要特殊处理。</li>
|
||||
*
|
||||
* <li>异步执行 {@link #executeAsync(SQLHandler, SQLExceptionHandler)}
|
||||
* <br>异步执行时将提供成功与异常两种处理方式
|
||||
* <br>可自行选择是否对数据或异常进行处理
|
||||
* <br>默认的异常处理器为 {@link #defaultExceptionHandler()}
|
||||
* <br>若有特殊需要,可通过{@link #setExceptionHandler(SQLExceptionHandler)} 方法修改默认的处理器</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <T> 需要返回的类型
|
||||
* @author CarmJos
|
||||
* @since 0.0.1
|
||||
*/
|
||||
public interface SQLAction<T> {
|
||||
|
||||
/**
|
||||
* 得到该Action的UUID
|
||||
*
|
||||
* @return UUID
|
||||
*/
|
||||
@NotNull UUID getActionUUID();
|
||||
|
||||
/**
|
||||
* 得到短八位格式的UUID
|
||||
*
|
||||
* @return UUID(8)
|
||||
*/
|
||||
@NotNull String getShortID();
|
||||
|
||||
/**
|
||||
* 得到该Action的创建时间。
|
||||
* <br>注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。
|
||||
*
|
||||
* @return 创建时间 (毫秒)
|
||||
*/
|
||||
default long getCreateTime() {
|
||||
return getCreateTime(TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到该Action的创建时间
|
||||
* <br>注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。
|
||||
*
|
||||
* @param unit 时间单位
|
||||
* @return 创建时间
|
||||
*/
|
||||
long getCreateTime(TimeUnit unit);
|
||||
|
||||
/**
|
||||
* 得到该Action所要执行的源SQL语句
|
||||
*
|
||||
* @return 源SQL语句
|
||||
*/
|
||||
@NotNull String getSQLContent();
|
||||
|
||||
/**
|
||||
* 得到该Action所要执行的源SQL语句列表。
|
||||
*
|
||||
* @return 源SQL语句列表
|
||||
*/
|
||||
default @NotNull List<String> getSQLContents() {
|
||||
return Collections.singletonList(getSQLContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到承载该Action的对应{@link SQLManager}
|
||||
*
|
||||
* @return {@link SQLManager}
|
||||
*/
|
||||
@NotNull SQLManager getManager();
|
||||
|
||||
/**
|
||||
* 执行该Action对应的SQL语句
|
||||
*
|
||||
* @return 指定数据类型
|
||||
* @throws SQLException 当SQL操作出现问题时抛出
|
||||
*/
|
||||
@NotNull T execute() throws SQLException;
|
||||
|
||||
|
||||
/**
|
||||
* 执行语句并返回值
|
||||
*
|
||||
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
|
||||
* @return 指定类型数据
|
||||
*/
|
||||
@Nullable
|
||||
default T execute(@Nullable SQLExceptionHandler exceptionHandler) {
|
||||
return execute(t -> t, exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行语句并处理返回值
|
||||
*
|
||||
* @param function 处理方法
|
||||
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
|
||||
* @param <R> 需要返回的内容
|
||||
* @return 指定类型数据
|
||||
*/
|
||||
@Nullable
|
||||
default <R> R execute(@NotNull SQLFunction<T, R> function,
|
||||
@Nullable SQLExceptionHandler exceptionHandler) {
|
||||
return execute(function, null, exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行语句并处理返回值
|
||||
*
|
||||
* @param function 处理方法
|
||||
* @param defaultResult 默认结果,若处理后的结果为null,则返回该值
|
||||
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
|
||||
* @param <R> 需要返回的内容
|
||||
* @return 指定类型数据
|
||||
*/
|
||||
@Nullable
|
||||
@Contract("_,!null,_ -> !null")
|
||||
default <R> R execute(@NotNull SQLFunction<T, R> function,
|
||||
@Nullable R defaultResult,
|
||||
@Nullable SQLExceptionHandler exceptionHandler) {
|
||||
try {
|
||||
return executeFunction(function, defaultResult);
|
||||
} catch (SQLException exception) {
|
||||
handleException(exceptionHandler, exception);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行语句并处理返回值
|
||||
*
|
||||
* @param function 处理方法
|
||||
* @param <R> 需要返回的内容
|
||||
* @return 指定类型数据
|
||||
* @throws SQLException 当SQL操作出现问题时抛出
|
||||
*/
|
||||
@Nullable
|
||||
default <R> R executeFunction(@NotNull SQLFunction<@NotNull T, R> function) throws SQLException {
|
||||
return executeFunction(function, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行语句并处理返回值
|
||||
*
|
||||
* @param function 处理方法
|
||||
* @param defaultResult 默认结果,若处理后的结果为null,则返回该值
|
||||
* @param <R> 需要返回的内容
|
||||
* @return 指定类型数据
|
||||
* @throws SQLException 当SQL操作出现问题时抛出
|
||||
*/
|
||||
@Nullable
|
||||
@Contract("_,!null -> !null")
|
||||
default <R> R executeFunction(@NotNull SQLFunction<@NotNull T, R> function,
|
||||
@Nullable R defaultResult) throws SQLException {
|
||||
try {
|
||||
R result = function.apply(execute());
|
||||
return result == null ? defaultResult : result;
|
||||
} catch (SQLException exception) {
|
||||
throw new SQLException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步执行SQL语句,采用默认异常处理,无需返回值。
|
||||
*/
|
||||
default void executeAsync() {
|
||||
executeAsync(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步执行SQL语句
|
||||
*
|
||||
* @param success 成功时的操作
|
||||
*/
|
||||
default void executeAsync(@Nullable SQLHandler<T> success) {
|
||||
executeAsync(success, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步执行SQL语句
|
||||
*
|
||||
* @param success 成功时的操作
|
||||
* @param failure 异常处理器 默认为 {@link SQLAction#defaultExceptionHandler()}
|
||||
*/
|
||||
void executeAsync(@Nullable SQLHandler<T> success,
|
||||
@Nullable SQLExceptionHandler failure);
|
||||
|
||||
/**
|
||||
* 以异步Future方式执行SQL语句。
|
||||
*
|
||||
* @return 异步执行的Future实例,可通过 {@link Future#get()} 阻塞并等待结果。
|
||||
*/
|
||||
default @NotNull CompletableFuture<Void> executeFuture() {
|
||||
return executeFuture((t -> null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 以异步Future方式执行SQL语句。
|
||||
*
|
||||
* @return 异步执行的Future实例,可通过 {@link Future#get()} 阻塞并等待结果。
|
||||
*/
|
||||
<R> @NotNull CompletableFuture<R> executeFuture(@NotNull SQLFunction<T, R> handler);
|
||||
|
||||
default void handleException(@Nullable SQLExceptionHandler handler, SQLException exception) {
|
||||
if (handler == null) handler = defaultExceptionHandler();
|
||||
handler.accept(exception, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理器提供的默认异常处理器。
|
||||
* 若未使用过 {@link #setExceptionHandler(SQLExceptionHandler)} 方法,
|
||||
* 则默认返回 {@link SQLExceptionHandler#detailed(Logger)} 。
|
||||
*
|
||||
* @return {@link SQLExceptionHandler}
|
||||
*/
|
||||
default SQLExceptionHandler defaultExceptionHandler() {
|
||||
return getManager().getExceptionHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设定通用的异常处理器。
|
||||
* <br> 在使用 {@link #execute(SQLExceptionHandler)} 等相关方法时,若传入的处理器为null,则会采用此处理器。
|
||||
* <br> 若该方法传入参数为 null,则会使用 {@link #defaultExceptionHandler()} 。
|
||||
*
|
||||
* @param handler 异常处理器
|
||||
*/
|
||||
default void setExceptionHandler(@Nullable SQLExceptionHandler handler) {
|
||||
getManager().setExceptionHandler(handler);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* SQLBuilder 是用于构建SQL语句以生成SQLAction执行操作的中间类。
|
||||
* <br>其连接了{@link SQLManager} 与 {@link SQLAction} ,避免大量的代码堆积
|
||||
* <br>也是本接口的核心功能所在
|
||||
*
|
||||
* @author CarmJos
|
||||
*/
|
||||
public interface SQLBuilder {
|
||||
|
||||
static @NotNull String withBackQuote(@NotNull String str) {
|
||||
str = str.trim();
|
||||
return !str.isEmpty() && str.charAt(0) == '`' && str.charAt(str.length() - 1) == '`' ? str : "`" + str + "`";
|
||||
}
|
||||
|
||||
static @NotNull String withQuote(@NotNull String str) {
|
||||
str = str.trim();
|
||||
return !str.isEmpty() && str.charAt(0) == '\'' && str.charAt(str.length() - 1) == '\'' ? str : "'" + str + "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到承载该Builder的对应{@link SQLManager}
|
||||
*
|
||||
* @return {@link SQLManager}
|
||||
*/
|
||||
@NotNull SQLManager getManager();
|
||||
|
||||
}
|
|
@ -1,316 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateBatchAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.*;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLBiFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLDebugHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLExceptionHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* SQLManager 是EasySQL的核心类,用于管理数据库连接,提供数据库操作的方法。
|
||||
*
|
||||
* @author CarmJos
|
||||
*/
|
||||
public interface SQLManager {
|
||||
|
||||
Logger getLogger();
|
||||
|
||||
boolean isDebugMode();
|
||||
|
||||
|
||||
/**
|
||||
* 获取用于执行 {@link SQLAction#executeAsync()} 的线程池。
|
||||
* <br> 默认线程池为 {@link #defaultExecutorPool(String)} 。
|
||||
*
|
||||
* @return {@link ExecutorService}
|
||||
*/
|
||||
@NotNull ExecutorService getExecutorPool();
|
||||
|
||||
/**
|
||||
* 设定用于执行 {@link SQLAction#executeAsync()} 的线程池.
|
||||
* <br> 默认线程池为 {@link #defaultExecutorPool(String)} 。
|
||||
*
|
||||
* @param executorPool {@link ExecutorService}
|
||||
*/
|
||||
void setExecutorPool(@NotNull ExecutorService executorPool);
|
||||
|
||||
static ExecutorService defaultExecutorPool(String threadName) {
|
||||
return Executors.newFixedThreadPool(4, r -> {
|
||||
Thread thread = new Thread(r, threadName);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设定是否启用调试模式。
|
||||
* 启用调试模式后,会在每次执行SQL语句时,调用 {@link #getDebugHandler()} 来输出调试信息。
|
||||
*
|
||||
* @param debugMode 是否启用调试模式
|
||||
*/
|
||||
void setDebugMode(@NotNull Supplier<@NotNull Boolean> debugMode);
|
||||
|
||||
/**
|
||||
* 设定是否启用调试模式。
|
||||
* 启用调试模式后,会在每次执行SQL语句时,调用 {@link #getDebugHandler()} 来输出调试信息。
|
||||
*
|
||||
* @param enable 是否启用调试模式
|
||||
*/
|
||||
default void setDebugMode(boolean enable) {
|
||||
setDebugMode(() -> enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调试处理器,用于处理调试信息。
|
||||
*
|
||||
* @return {@link SQLDebugHandler}
|
||||
*/
|
||||
@NotNull SQLDebugHandler getDebugHandler();
|
||||
|
||||
/**
|
||||
* 设定调试处理器,默认为 {@link SQLDebugHandler#defaultHandler(Logger)} 。
|
||||
*
|
||||
* @param debugHandler {@link SQLDebugHandler}
|
||||
*/
|
||||
void setDebugHandler(@NotNull SQLDebugHandler debugHandler);
|
||||
|
||||
/**
|
||||
* 得到连接池源
|
||||
*
|
||||
* @return DataSource
|
||||
*/
|
||||
@NotNull DataSource getDataSource();
|
||||
|
||||
/**
|
||||
* 得到一个数据库连接实例
|
||||
*
|
||||
* @return Connection
|
||||
* @throws SQLException 见 {@link DataSource#getConnection()}
|
||||
*/
|
||||
@NotNull Connection getConnection() throws SQLException;
|
||||
|
||||
/**
|
||||
* 得到正使用的查询。
|
||||
*
|
||||
* @return 查询列表
|
||||
*/
|
||||
@NotNull Map<UUID, SQLQuery> getActiveQuery();
|
||||
|
||||
/**
|
||||
* 获取改管理器提供的默认异常处理器。
|
||||
* 若未使用过 {@link #setExceptionHandler(SQLExceptionHandler)} 方法,
|
||||
* 则默认返回 {@link SQLExceptionHandler#detailed(Logger)} 。
|
||||
*
|
||||
* @return {@link SQLExceptionHandler}
|
||||
*/
|
||||
@NotNull SQLExceptionHandler getExceptionHandler();
|
||||
|
||||
/**
|
||||
* 设定通用的异常处理器。
|
||||
* <br> 在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时,若传入的处理器为null,则会采用此处理器。
|
||||
* <br> 若该方法传入参数为 null,则会使用 {@link SQLExceptionHandler#detailed(Logger)} 。
|
||||
*
|
||||
* @param handler 异常处理器
|
||||
*/
|
||||
void setExceptionHandler(@Nullable SQLExceptionHandler handler);
|
||||
|
||||
/**
|
||||
* 执行一条不需要返回结果的SQL语句(多用于UPDATE、REPLACE、DELETE方法)
|
||||
* 该方法使用 Statement 实现,请注意SQL注入风险!
|
||||
*
|
||||
* @param sql SQL语句内容
|
||||
* @return 更新的行数
|
||||
* @see SQLUpdateAction
|
||||
*/
|
||||
@Nullable Integer executeSQL(String sql);
|
||||
|
||||
/**
|
||||
* 执行一条不需要返回结果的预处理SQL更改(UPDATE、REPLACE、DELETE)
|
||||
*
|
||||
* @param sql SQL语句内容
|
||||
* @param params SQL语句中 ? 的对应参数
|
||||
* @return 更新的行数
|
||||
* @see PreparedSQLUpdateAction
|
||||
*/
|
||||
@Nullable Integer executeSQL(String sql, Object[] params);
|
||||
|
||||
/**
|
||||
* 执行多条不需要返回结果的SQL更改(UPDATE、REPLACE、DELETE)
|
||||
*
|
||||
* @param sql SQL语句内容
|
||||
* @param paramsBatch SQL语句中对应?的参数组
|
||||
* @return 对应参数返回的行数
|
||||
* @see PreparedSQLUpdateBatchAction
|
||||
*/
|
||||
@Nullable List<Integer> executeSQLBatch(String sql, Iterable<Object[]> paramsBatch);
|
||||
|
||||
|
||||
/**
|
||||
* 执行多条不需要返回结果的SQL。
|
||||
* 该方法使用 Statement 实现,请注意SQL注入风险!
|
||||
*
|
||||
* @param sql SQL语句内容
|
||||
* @param moreSQL 更多SQL语句内容
|
||||
* @return 对应参数返回的行数
|
||||
* @see SQLUpdateBatchAction
|
||||
*/
|
||||
@Nullable List<Integer> executeSQLBatch(@NotNull String sql, String... moreSQL);
|
||||
|
||||
/**
|
||||
* 执行多条不需要返回结果的SQL。
|
||||
*
|
||||
* @param sqlBatch SQL语句内容
|
||||
* @return 对应参数返回的行数
|
||||
*/
|
||||
@Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch);
|
||||
|
||||
/**
|
||||
* 获取并操作 {@link DatabaseMetaData} 以得到需要的数据库消息。
|
||||
*
|
||||
* @param reader 操作与读取的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
*/
|
||||
default <R> CompletableFuture<R> fetchMetadata(@NotNull SQLFunction<DatabaseMetaData, R> reader) {
|
||||
return fetchMetadata((meta, conn) -> reader.apply(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取并操作 {@link DatabaseMetaData} 提供的指定 {@link ResultSet} 以得到需要的数据库消息。
|
||||
* <br> 该方法会自动关闭 {@link ResultSet} 。
|
||||
*
|
||||
* @param supplier 操作 {@link DatabaseMetaData} 以提供信息所在的 {@link ResultSet}
|
||||
* @param reader 读取 {@link ResultSet} 中指定信息的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
* @throws NullPointerException 当 supplier 提供的 {@link ResultSet} 为NULL时抛出
|
||||
*/
|
||||
default <R> CompletableFuture<R> fetchMetadata(@NotNull SQLFunction<DatabaseMetaData, ResultSet> supplier,
|
||||
@NotNull SQLFunction<@NotNull ResultSet, R> reader) {
|
||||
return fetchMetadata((meta, conn) -> supplier.apply(meta), reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取并操作 {@link DatabaseMetaData} 以得到需要的数据库消息。
|
||||
*
|
||||
* @param reader 操作与读取的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
*/
|
||||
<R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, R> reader);
|
||||
|
||||
/**
|
||||
* 获取并操作 {@link DatabaseMetaData} 提供的指定 {@link ResultSet} 以得到需要的数据库消息。
|
||||
* <br> 该方法会自动关闭 {@link ResultSet} 。
|
||||
*
|
||||
* @param supplier 操作 {@link DatabaseMetaData} 以提供信息所在的 {@link ResultSet}
|
||||
* @param reader 读取 {@link ResultSet} 中指定信息的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
* @throws NullPointerException 当 supplier 提供的 {@link ResultSet} 为NULL时抛出
|
||||
*/
|
||||
<R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, ResultSet> supplier,
|
||||
@NotNull SQLFunction<@NotNull ResultSet, R> reader);
|
||||
|
||||
/**
|
||||
* 在库中创建一个表。
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
TableCreateBuilder createTable(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 对库中的某个表执行更改。
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return {@link TableAlterBuilder}
|
||||
*/
|
||||
TableAlterBuilder alterTable(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 快速获取表的部分元数据。
|
||||
* <br> 当需要获取其他元数据时,请使用 {@link #fetchMetadata(SQLFunction, SQLFunction)} 方法。
|
||||
*
|
||||
* @param tablePattern 表名通配符
|
||||
* @return {@link TableMetadataBuilder}
|
||||
*/
|
||||
TableMetadataBuilder fetchTableMetadata(@NotNull String tablePattern);
|
||||
|
||||
/**
|
||||
* 新建一个查询。
|
||||
*
|
||||
* @return {@link QueryBuilder}
|
||||
*/
|
||||
QueryBuilder createQuery();
|
||||
|
||||
/**
|
||||
* 创建一条插入操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link InsertBuilder}
|
||||
*/
|
||||
InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建支持多组数据的插入操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link InsertBuilder}
|
||||
*/
|
||||
InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建一条替换操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link ReplaceBuilder}
|
||||
*/
|
||||
ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建支持多组数据的替换操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link ReplaceBuilder}
|
||||
*/
|
||||
ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建更新操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link UpdateBuilder}
|
||||
*/
|
||||
UpdateBuilder createUpdate(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建删除操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link DeleteBuilder}
|
||||
*/
|
||||
DeleteBuilder createDelete(@NotNull String tableName);
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.PreparedQueryAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.QueryAction;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* SQLQuery 是一个查询中间接口,用于查询操作的封装。
|
||||
*
|
||||
* @author CarmJos
|
||||
*/
|
||||
public interface SQLQuery extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* 获取该查询创建的时间
|
||||
* <br>注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。
|
||||
*
|
||||
* @return 创建时间
|
||||
*/
|
||||
default long getExecuteTime() {
|
||||
return getExecuteTime(TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该查询创建的时间
|
||||
* <br>注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。
|
||||
*
|
||||
* @param timeUnit 时间单位
|
||||
* @return 创建时间
|
||||
*/
|
||||
long getExecuteTime(TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* 得到承载该SQLQuery的对应{@link SQLManager}
|
||||
*
|
||||
* @return {@link SQLManager}
|
||||
*/
|
||||
SQLManager getManager();
|
||||
|
||||
/**
|
||||
* 得到承载该SQLQuery的对应{@link QueryAction}
|
||||
*
|
||||
* @return {@link QueryAction} 或 {@link PreparedQueryAction}
|
||||
*/
|
||||
QueryAction getAction();
|
||||
|
||||
ResultSet getResultSet();
|
||||
|
||||
default boolean containsResult(String columnName) throws SQLException {
|
||||
return getResultSet() != null && getResultSet().getObject(columnName) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到设定的SQL语句
|
||||
*
|
||||
* @return SQL语句
|
||||
*/
|
||||
String getSQLContent();
|
||||
|
||||
/**
|
||||
* 关闭所有内容
|
||||
*/
|
||||
@Override
|
||||
void close();
|
||||
|
||||
Statement getStatement();
|
||||
|
||||
Connection getConnection();
|
||||
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.*;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.table.NamedSQLTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* SQLTable 基于 {@link TableCreateBuilder} 构建表,用于快速创建与该表相关的操作。
|
||||
* <ul>
|
||||
* <li>1. 调用 {@link NamedSQLTable#of(String, String[])} 方法创建一个 SQLTable 对象;</li>
|
||||
* <li>2. 在应用初始化阶段调用 {@link NamedSQLTable#create(SQLManager)} 方法初始化 SQLTable 对象;</li>
|
||||
* <li>3. 获取已创建的{@link NamedSQLTable} 实例,直接调用对应方法进行关于表的相关操作。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author CarmJos
|
||||
* @since 0.3.10
|
||||
*/
|
||||
public interface SQLTable {
|
||||
|
||||
static @NotNull NamedSQLTable of(@NotNull String tableName, @Nullable SQLHandler<TableCreateBuilder> table) {
|
||||
return new NamedSQLTable(tableName) {
|
||||
@Override
|
||||
public boolean create(@NotNull SQLManager sqlManager, String tablePrefix) throws SQLException {
|
||||
if (this.manager == null) this.manager = sqlManager;
|
||||
this.tablePrefix = tablePrefix;
|
||||
|
||||
TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName());
|
||||
if (table != null) table.accept(tableBuilder);
|
||||
return tableBuilder.build().executeFunction(l -> l > 0, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static @NotNull NamedSQLTable of(@NotNull String tableName, @NotNull String[] columns) {
|
||||
return of(tableName, columns, null);
|
||||
}
|
||||
|
||||
static @NotNull NamedSQLTable of(@NotNull String tableName,
|
||||
@NotNull String[] columns, @Nullable String tableSettings) {
|
||||
return of(tableName, builder -> {
|
||||
builder.setColumns(columns);
|
||||
if (tableSettings != null) builder.setTableSettings(tableSettings);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 以指定的 {@link SQLManager} 实例初始化并创建该表
|
||||
*
|
||||
* @param sqlManager {@link SQLManager} 实例
|
||||
* @return 是否新创建了本表 (若已创建或创建失败则返回false)
|
||||
* @throws SQLException 当数据库返回异常时抛出
|
||||
*/
|
||||
boolean create(SQLManager sqlManager) throws SQLException;
|
||||
|
||||
/**
|
||||
* 得到 {@link #create(SQLManager)} 用于初始化本实例的 {@link SQLManager} 实例
|
||||
*
|
||||
* @return {@link SQLManager} 实例
|
||||
*/
|
||||
@Nullable SQLManager getSQLManager();
|
||||
|
||||
/**
|
||||
* 得到本表表名,不得为空。
|
||||
*
|
||||
* @return 本表表名
|
||||
*/
|
||||
@NotNull String getTableName();
|
||||
|
||||
default @NotNull TableQueryBuilder createQuery() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createQuery)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
}
|
||||
|
||||
default @NotNull TableQueryBuilder createQuery(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.createQuery().inTable(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull DeleteBuilder createDelete() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createDelete)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
}
|
||||
|
||||
default @NotNull DeleteBuilder createDelete(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.createDelete(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull UpdateBuilder createUpdate() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createUpdate)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
}
|
||||
|
||||
default @NotNull UpdateBuilder createUpdate(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.createUpdate(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createInsert)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
}
|
||||
|
||||
default @NotNull InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.createInsert(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createInsertBatch)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
}
|
||||
|
||||
default @NotNull InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.createInsertBatch(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createReplace)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
|
||||
}
|
||||
|
||||
default @NotNull ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.createReplace(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createReplaceBatch)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
}
|
||||
|
||||
default @NotNull ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.createReplaceBatch(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull TableAlterBuilder alter() {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::alter)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
}
|
||||
|
||||
default @NotNull TableAlterBuilder alter(@NotNull SQLManager sqlManager) {
|
||||
return sqlManager.alterTable(getTableName());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.action;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PreparedSQLUpdateAction<T extends Number> extends SQLUpdateAction<T> {
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedSQLUpdateAction}
|
||||
*/
|
||||
PreparedSQLUpdateAction<T> setParams(Object... params);
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedSQLUpdateAction}
|
||||
* @since 0.4.0
|
||||
*/
|
||||
PreparedSQLUpdateAction<T> setParams(@Nullable Iterable<Object> params);
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PreparedSQLUpdateBatchAction<T extends Number> extends SQLAction<List<T>> {
|
||||
|
||||
/**
|
||||
* 设定多组SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param allParams 所有参数内容
|
||||
* @return {@link PreparedSQLUpdateBatchAction}
|
||||
*/
|
||||
PreparedSQLUpdateBatchAction<T> setAllParams(Iterable<Object[]> allParams);
|
||||
|
||||
/**
|
||||
* 添加一组SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedSQLUpdateBatchAction}
|
||||
*/
|
||||
PreparedSQLUpdateBatchAction<T> addParamsBatch(Object... params);
|
||||
|
||||
/**
|
||||
* 设定该操作返回自增键序列。
|
||||
*
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
PreparedSQLUpdateBatchAction<T> returnGeneratedKeys();
|
||||
|
||||
/**
|
||||
* 设定该操作返回自增键序列。
|
||||
*
|
||||
* @param keyTypeClass 自增序列的数字类型
|
||||
* @param <N> 自增键序列类型 {@link Number}
|
||||
* @return {@link SQLUpdateAction}
|
||||
* @since 0.4.0
|
||||
*/
|
||||
<N extends Number> PreparedSQLUpdateBatchAction<N> returnGeneratedKeys(Class<N> keyTypeClass);
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
|
||||
public interface SQLUpdateAction<T extends Number> extends SQLAction<T> {
|
||||
|
||||
|
||||
/**
|
||||
* 设定该操作返回自增键序列。
|
||||
*
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
SQLUpdateAction<T> returnGeneratedKey();
|
||||
|
||||
/**
|
||||
* 设定该操作返回自增键序列。
|
||||
*
|
||||
* @param keyTypeClass 自增序列的数字类型
|
||||
* @param <N> 自增键序列类型 {@link Number}
|
||||
* @return {@link SQLUpdateAction}
|
||||
* @since 0.4.0
|
||||
*/
|
||||
<N extends Number> SQLUpdateAction<N> returnGeneratedKey(Class<N> keyTypeClass);
|
||||
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.action;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public interface SQLUpdateBatchAction extends SQLAction<List<Integer>> {
|
||||
|
||||
/**
|
||||
* 添加一条批量执行的SQL语句
|
||||
*
|
||||
* @param sql SQL语句
|
||||
* @return {@link SQLUpdateBatchAction}
|
||||
*/
|
||||
SQLUpdateBatchAction addBatch(@NotNull String sql);
|
||||
|
||||
@Override
|
||||
default @NotNull String getSQLContent() {
|
||||
return getSQLContents().get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull List<String> getSQLContents();
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.action.query;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface PreparedQueryAction extends QueryAction {
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction setParams(@Nullable Object... params);
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction setParams(@Nullable Iterable<Object> params);
|
||||
|
||||
/**
|
||||
* 直接对 {@link PreparedStatement} 进行处理
|
||||
*
|
||||
* @param statement {@link Consumer} 处理操作
|
||||
* 若为空则不进行处理
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction handleStatement(@Nullable Consumer<PreparedStatement> statement);
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.action.query;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLQuery;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLExceptionHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLHandler;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* SQLQueryAction 是用于承载SQL查询语句并进行处理、返回并自动关闭连接的基本类。
|
||||
*
|
||||
* <ul>
|
||||
* <li>同步执行 {@link #execute()}, {@link #execute(SQLFunction, SQLExceptionHandler)}
|
||||
* <br>同步执行方法中有会抛出异常的方法与不抛出异常的方法,
|
||||
* <br>若选择不抛出异常,则返回值可能为空,需要特殊处理。</li>
|
||||
*
|
||||
* <li>异步执行 {@link #executeAsync(SQLHandler, SQLExceptionHandler)}
|
||||
* <br>异步执行时将提供成功与异常两种处理方式
|
||||
* <br>可自行选择是否对数据或异常进行处理
|
||||
* <br>默认的异常处理器为 {@link #defaultExceptionHandler()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <b>注意: 无论是否异步,都不需要自行关闭ResultSet,本API已自动关闭</b>
|
||||
*
|
||||
* @author CarmJos
|
||||
* @since 0.2.6
|
||||
*/
|
||||
public interface QueryAction extends SQLAction<SQLQuery> {
|
||||
|
||||
@Override
|
||||
@Contract("_,!null -> !null")
|
||||
default <R> @Nullable R executeFunction(@NotNull SQLFunction<@NotNull SQLQuery, R> function,
|
||||
@Nullable R defaultResult) throws SQLException {
|
||||
try (SQLQuery value = execute()) {
|
||||
R result = function.apply(value);
|
||||
return result == null ? defaultResult : result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public interface ConditionalBuilder<B extends ConditionalBuilder<B, T>, T extends SQLAction<?>> extends SQLBuilder {
|
||||
|
||||
/**
|
||||
* 将现有条件构建完整的SQL语句用于执行。
|
||||
*
|
||||
* @return {@link SQLAction}
|
||||
*/
|
||||
T build();
|
||||
|
||||
/**
|
||||
* 设定限定的条目数
|
||||
*
|
||||
* @param limit 条数限制
|
||||
* @return {@link B}
|
||||
*/
|
||||
B setLimit(int limit);
|
||||
|
||||
/**
|
||||
* 直接设定条件的源文本,不需要以WHERE开头。
|
||||
* <br>如 {@code id = 1 AND name = 'test' OR name = 'test2'} 。
|
||||
*
|
||||
* @param condition 条件文本,不需要以WHERE开头。
|
||||
* @return {@link B}
|
||||
*/
|
||||
B setConditions(@Nullable String condition);
|
||||
|
||||
/**
|
||||
* 直接设定每个条件的文本与其对应数值,将以AND链接,且不需要以WHERE开头。
|
||||
* <br>条件如 {@code id = ? },问号将被以对应的数值填充。。
|
||||
*
|
||||
* @param conditionSQLs 条件内容,将以AND链接,且不需要以WHERE开头。
|
||||
* @return {@link B}
|
||||
*/
|
||||
B setConditions(LinkedHashMap<@NotNull String, @Nullable Object> conditionSQLs);
|
||||
|
||||
B addCondition(@Nullable String condition);
|
||||
|
||||
B addCondition(@NotNull String columnName, @NotNull String operator, @Nullable Object queryValue);
|
||||
|
||||
B addCondition(@NotNull String columnName, @Nullable Object queryValue);
|
||||
|
||||
B addCondition(@NotNull String[] columnNames, @Nullable Object[] queryValues);
|
||||
|
||||
B addNotNullCondition(@NotNull String columnName);
|
||||
|
||||
/**
|
||||
* 添加时间的限定条件。 若设定了开始时间,则限定条件为 {@code endMillis >= startMillis};
|
||||
*
|
||||
* @param columnName 判断的行
|
||||
* @param startMillis 开始时间戳,若{@code <0}则不作限定
|
||||
* @param endMillis 结束时间戳,若{@code <0}则不作限定
|
||||
* @return {@link B}
|
||||
*/
|
||||
default B addTimeCondition(@NotNull String columnName, long startMillis, long endMillis) {
|
||||
return addTimeCondition(columnName,
|
||||
startMillis > 0 ? new Date(startMillis) : null,
|
||||
endMillis > 0 ? new Date(endMillis) : null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加时间的限定条件。 若设定了开始时间,则限定条件为 {@code endDate >= startTime};
|
||||
*
|
||||
* @param columnName 判断的行
|
||||
* @param startDate 开始时间,若为null则不作限定
|
||||
* @param endDate 结束时间,若为null则不作限定
|
||||
* @return {@link B}
|
||||
*/
|
||||
B addTimeCondition(@NotNull String columnName, @Nullable Date startDate, @Nullable Date endDate);
|
||||
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
|
||||
public interface DeleteBuilder extends ConditionalBuilder<DeleteBuilder, SQLAction<Integer>> {
|
||||
|
||||
String getTableName();
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface InsertBuilder<T extends SQLAction<?>> {
|
||||
|
||||
String getTableName();
|
||||
|
||||
boolean isIgnore();
|
||||
|
||||
InsertBuilder<T> setIgnore(boolean ignore);
|
||||
|
||||
T setColumnNames(List<String> columnNames);
|
||||
|
||||
default T setColumnNames(String... columnNames) {
|
||||
return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.PreparedQueryAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.QueryAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface QueryBuilder extends SQLBuilder {
|
||||
|
||||
/**
|
||||
* 通过一条 SQL语句创建查询。
|
||||
* 该方法使用 Statement 实现,请注意SQL注入风险!
|
||||
*
|
||||
* @param sql SQL语句
|
||||
* @return {@link QueryAction}
|
||||
* @deprecated 存在SQL注入风险,建议使用 {@link QueryBuilder#withPreparedSQL(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
QueryAction withSQL(@NotNull String sql);
|
||||
|
||||
/**
|
||||
* 通过一条 SQL语句创建预查询
|
||||
*
|
||||
* @param sql SQL语句
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction withPreparedSQL(@NotNull String sql);
|
||||
|
||||
/**
|
||||
* 创建表查询
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return {@link TableQueryBuilder}
|
||||
*/
|
||||
TableQueryBuilder inTable(@NotNull String tableName);
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* REPLACE 语句用于将一组值更新进数据表中。
|
||||
* <br> 执行后,将通过表中键判断该数据是否存在,若存在则用新数据替换原来的值,若不存在则会插入该数据。
|
||||
* <br> 在使用REPLACE时,表与所给行列数据中必须包含唯一索引(或主键),且索引不得为空值,否则将等同于插入语句。
|
||||
*
|
||||
* @param <T> 最终构建出的 {@link SQLAction} 类型
|
||||
*/
|
||||
public interface ReplaceBuilder<T extends SQLAction<?>> {
|
||||
|
||||
String getTableName();
|
||||
|
||||
T setColumnNames(List<String> columnNames);
|
||||
|
||||
default T setColumnNames(String... columnNames) {
|
||||
return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.IndexType;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.NumberType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface TableAlterBuilder extends SQLBuilder {
|
||||
|
||||
SQLAction<Integer> renameTo(@NotNull String newTableName);
|
||||
|
||||
SQLAction<Integer> changeComment(@NotNull String newTableComment);
|
||||
|
||||
SQLAction<Integer> setAutoIncrementIndex(int index);
|
||||
|
||||
SQLAction<Integer> addIndex(@NotNull IndexType indexType, @Nullable String indexName,
|
||||
@NotNull String columnName, @NotNull String... moreColumns);
|
||||
|
||||
/**
|
||||
* 为该表移除一个索引
|
||||
*
|
||||
* @param indexName 索引名
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
SQLAction<Integer> dropIndex(@NotNull String indexName);
|
||||
|
||||
/**
|
||||
* 为该表移除一个外键
|
||||
*
|
||||
* @param keySymbol 外键名
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
SQLAction<Integer> dropForeignKey(@NotNull String keySymbol);
|
||||
|
||||
/**
|
||||
* 为该表移除主键(须添加新主键)
|
||||
*
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
SQLAction<Integer> dropPrimaryKey();
|
||||
|
||||
/**
|
||||
* 为表添加一列
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param settings 列的相关设定
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
default SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings) {
|
||||
return addColumn(columnName, settings, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为表添加一列
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param settings 列的相关设定
|
||||
* @param afterColumn 该列增添到哪个列的后面,
|
||||
* <p> 该参数若省缺则放于最后一行
|
||||
* <p> 若为 "" 则置于首行。
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn);
|
||||
|
||||
SQLAction<Integer> renameColumn(@NotNull String columnName, @NotNull String newName);
|
||||
|
||||
SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String settings);
|
||||
|
||||
default SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String columnSettings, @NotNull String afterColumn) {
|
||||
return modifyColumn(columnName, columnSettings + " AFTER `" + afterColumn + "`");
|
||||
}
|
||||
|
||||
SQLAction<Integer> removeColumn(@NotNull String columnName);
|
||||
|
||||
SQLAction<Integer> setColumnDefault(@NotNull String columnName, @NotNull String defaultValue);
|
||||
|
||||
SQLAction<Integer> removeColumnDefault(@NotNull String columnName);
|
||||
|
||||
/**
|
||||
* 为该表添加一个自增列
|
||||
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
|
||||
* <p> 注意:一个表只允许有一个自增列!
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param numberType 数字类型,若省缺则为 {@link NumberType#INT}
|
||||
* @param primary 是否为主键,若否则只为唯一键
|
||||
* @param unsigned 是否采用 UNSIGNED (即无负数,可以增加自增键的最高数,建议为true)
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
|
||||
boolean primary, boolean unsigned) {
|
||||
return addColumn(columnName,
|
||||
(numberType == null ? NumberType.INT : numberType).name()
|
||||
+ (unsigned ? " UNSIGNED " : " ")
|
||||
+ "NOT NULL AUTO_INCREMENT " + (primary ? "PRIMARY KEY" : "UNIQUE KEY"),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为该表添加一个自增列
|
||||
* <br> 自增列强制要求为数字类型,非空,且为UNIQUE。
|
||||
* <p> 注意:一个表只允许有一个自增列!
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param numberType 数字类型,若省缺则为 {@link NumberType#INT}
|
||||
* @return {@link TableAlterBuilder}
|
||||
*/
|
||||
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName, @NotNull NumberType numberType) {
|
||||
return addAutoIncrementColumn(columnName, numberType, false, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 为该表添加一个自增列
|
||||
* <br> 自增列强制要求为数字类型,非空,且为UNIQUE。
|
||||
* <p> 注意:一个表只允许有一个自增列!
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @return {@link TableAlterBuilder}
|
||||
*/
|
||||
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName) {
|
||||
return addAutoIncrementColumn(columnName, NumberType.INT);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.ForeignKeyRule;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.IndexType;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.NumberType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withQuote;
|
||||
|
||||
|
||||
public interface TableCreateBuilder extends SQLBuilder {
|
||||
|
||||
/**
|
||||
* 将现有条件构建完整的SQL语句用于执行。
|
||||
*
|
||||
* @return {@link SQLUpdateAction}
|
||||
*/
|
||||
SQLUpdateAction<Integer> build();
|
||||
|
||||
@NotNull String getTableName();
|
||||
|
||||
/**
|
||||
* 得到表的设定。
|
||||
* <p> 若未使用 {@link #setTableSettings(String)} 方法则会采用 {@link #defaultTablesSettings()} 。
|
||||
*
|
||||
* @return TableSettings
|
||||
*/
|
||||
@NotNull String getTableSettings();
|
||||
|
||||
TableCreateBuilder setTableSettings(@NotNull String settings);
|
||||
|
||||
/**
|
||||
* 设定表的标注,一般用于解释该表的作用。
|
||||
*
|
||||
* @param comment 表标注
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
TableCreateBuilder setTableComment(@Nullable String comment);
|
||||
|
||||
/**
|
||||
* 直接设定表的所有列信息
|
||||
*
|
||||
* @param columns 列的相关信息 (包括列设定)
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
TableCreateBuilder setColumns(@NotNull String... columns);
|
||||
|
||||
/**
|
||||
* 为该表添加一个列
|
||||
*
|
||||
* @param column 列的相关信息
|
||||
* <br>如 `uuid` VARCHAR(36) NOT NULL UNIQUE KEY
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
TableCreateBuilder addColumn(@NotNull String column);
|
||||
|
||||
/**
|
||||
* 为该表添加一个列
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param settings 列的设定
|
||||
* <br>如 VARCHAR(36) NOT NULL UNIQUE KEY
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
return addColumn(withBackQuote(columnName) + " " + settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为该表添加一个列
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param settings 列的设定
|
||||
* <br>如 VARCHAR(36) NOT NULL UNIQUE KEY
|
||||
* @param comments 列的注解,用于解释该列数据的作用
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings, @NotNull String comments) {
|
||||
return addColumn(columnName, settings + " COMMENT " + withQuote(comments));
|
||||
}
|
||||
|
||||
/**
|
||||
* 为该表添加一个自增列
|
||||
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
|
||||
* <p> 注意:一个表只允许有一个自增列!
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param numberType 数字类型,若省缺则为 {@link NumberType#INT}
|
||||
* @param asPrimaryKey 是否为主键,若为false则设定为唯一键
|
||||
* @param unsigned 是否采用 UNSIGNED (即无负数,可以增加自增键的最高数,建议为true)
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
|
||||
boolean asPrimaryKey, boolean unsigned);
|
||||
|
||||
/**
|
||||
* 为该表添加一个INT类型的自增主键列
|
||||
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
|
||||
* <p> 注意:一个表只允许有一个自增列!
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param asPrimaryKey 是否为主键,若为false则设定为唯一键
|
||||
* @param unsigned 是否采用 UNSIGNED (即无负数,可以增加自增键的最高数,建议为true)
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName,
|
||||
boolean asPrimaryKey, boolean unsigned) {
|
||||
return addAutoIncrementColumn(columnName, NumberType.INT, asPrimaryKey, unsigned);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 为该表添加一个INT类型的自增列
|
||||
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
|
||||
* <p> 注意:一个表只允许有一个自增列!
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @param asPrimaryKey 是否为主键,若为false则设定为唯一键
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, boolean asPrimaryKey) {
|
||||
return addAutoIncrementColumn(columnName, asPrimaryKey, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为该表添加一个INT类型的自增主键列
|
||||
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
|
||||
* <p> 注意:一个表只允许有一个自增列!
|
||||
*
|
||||
* @param columnName 列名
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName) {
|
||||
return addAutoIncrementColumn(columnName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设定表中的某列为索引或键。
|
||||
*
|
||||
* <p>创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
|
||||
* <br>虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE 和DELETE。
|
||||
* <br>因此,请合理的设计索引。
|
||||
*
|
||||
* @param type 索引类型
|
||||
* @param columnName 索引包含的列
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder setIndex(@NotNull String columnName,
|
||||
@NotNull IndexType type) {
|
||||
return setIndex(type, null, columnName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设定表中的某列为索引或键。
|
||||
*
|
||||
* <p>创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
|
||||
* <br>虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE 和DELETE。
|
||||
* <br>因此,请合理的设计索引。
|
||||
*
|
||||
* @param type 索引类型
|
||||
* @param indexName 索引名称,缺省时将根据第一个索引列赋一个名称
|
||||
* @param columnName 索引包含的列
|
||||
* @param moreColumns 联合索引需要包含的列
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
TableCreateBuilder setIndex(@NotNull IndexType type, @Nullable String indexName,
|
||||
@NotNull String columnName, @NotNull String... moreColumns);
|
||||
|
||||
|
||||
/**
|
||||
* 以本表位从表,为表中某列设定自参照外键(即自参照完整性)。
|
||||
*
|
||||
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
|
||||
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
|
||||
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
|
||||
*
|
||||
* @param tableColumn 本表中的列
|
||||
* @param foreignColumn 外键关联表中对应的关联列,必须为目标表的主键,即 {@link IndexType#PRIMARY_KEY}
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addForeignKey(@NotNull String tableColumn, @NotNull String foreignColumn) {
|
||||
return addForeignKey(tableColumn, getTableName(), foreignColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以本表位从表,为表中某列设定外键。
|
||||
*
|
||||
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
|
||||
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
|
||||
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
|
||||
*
|
||||
* @param tableColumn 本表中的列
|
||||
* @param foreignTable 外键关联主表,必须为已存在的表或本表,且必须有主键。
|
||||
* @param foreignColumn 外键关联主表中对应的关联列,须满足
|
||||
* <p> 1. 为主表的主键,即 {@link IndexType#PRIMARY_KEY}
|
||||
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同。
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addForeignKey(@NotNull String tableColumn,
|
||||
@NotNull String foreignTable, @NotNull String foreignColumn) {
|
||||
return addForeignKey(tableColumn, null, foreignTable, foreignColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以本表位从表,为表中某列设定外键。
|
||||
*
|
||||
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
|
||||
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
|
||||
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
|
||||
*
|
||||
* @param tableColumn 本表中的列
|
||||
* @param constraintName 约束名,缺省时将使用参数自动生成,如 <i>fk_[tableColumn]_[foreignTable]</i>
|
||||
* @param foreignTable 外键关联主表,必须为已存在的表或本表,且必须有主键。
|
||||
* @param foreignColumn 外键关联主表中对应的关联列,须满足
|
||||
* <p> 1. 为主表的主键,即 {@link IndexType#PRIMARY_KEY}
|
||||
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同。
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
default TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
|
||||
@NotNull String foreignTable, @NotNull String foreignColumn) {
|
||||
return addForeignKey(tableColumn, constraintName, foreignTable, foreignColumn, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以本表位从表,为表中某列设定外键。
|
||||
*
|
||||
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
|
||||
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
|
||||
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
|
||||
*
|
||||
* @param tableColumn 本表中的列
|
||||
* @param constraintName 约束名,缺省时将使用参数自动生成,如 <i>fk_[tableColumn]_[foreignTable]</i>
|
||||
* @param foreignTable 外键关联主表,必须为已存在的表或本表,且必须有主键。
|
||||
* @param foreignColumn 外键关联主表中对应的关联列,须满足
|
||||
* <p> 1. 为主表的主键,即 {@link IndexType#PRIMARY_KEY}
|
||||
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同。
|
||||
* @param updateRule 在外键被更新时采用的规则,缺省时默认为{@link ForeignKeyRule#RESTRICT}
|
||||
* @param deleteRule 在外键被删除时采用的规则,缺省时默认为{@link ForeignKeyRule#RESTRICT}
|
||||
* @return {@link TableCreateBuilder}
|
||||
*/
|
||||
TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
|
||||
@NotNull String foreignTable, @NotNull String foreignColumn,
|
||||
@Nullable ForeignKeyRule updateRule, @Nullable ForeignKeyRule deleteRule);
|
||||
|
||||
default String defaultTablesSettings() {
|
||||
return "ENGINE=InnoDB DEFAULT CHARSET=utf8";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface TableMetadataBuilder extends SQLBuilder {
|
||||
|
||||
/**
|
||||
* @return 本表是否存在
|
||||
*/
|
||||
CompletableFuture<Boolean> validateExist();
|
||||
|
||||
/**
|
||||
* 对表内的数据列元数据进行读取
|
||||
*
|
||||
* @param columnPattern 列的名称匹配表达式, 为空则匹配所有列
|
||||
* @param reader 读取的方法
|
||||
* @param <R> 结果类型
|
||||
* @return 读取结果
|
||||
*/
|
||||
<R> CompletableFuture<R> fetchColumns(@Nullable String columnPattern,
|
||||
@NotNull SQLFunction<ResultSet, R> reader);
|
||||
|
||||
/**
|
||||
* @param columnPattern 需要判断的列名表达式
|
||||
* @return 对应列是否存在
|
||||
*/
|
||||
CompletableFuture<Boolean> isColumnExists(@NotNull String columnPattern);
|
||||
|
||||
/**
|
||||
* 列出所有表内的全部列。
|
||||
*
|
||||
* @return 表内全部数据列的列名
|
||||
*/
|
||||
default CompletableFuture<@Unmodifiable Set<String>> listColumns() {
|
||||
return listColumns(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出所有满足表达式的列。
|
||||
*
|
||||
* @param columnPattern 列名表达式,为空则列出全部
|
||||
* @return 所有满足表达式的列名
|
||||
*/
|
||||
CompletableFuture<@Unmodifiable Set<String>> listColumns(@Nullable String columnPattern);
|
||||
|
||||
// More coming soon.
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.PreparedQueryAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface TableQueryBuilder extends ConditionalBuilder<TableQueryBuilder, PreparedQueryAction> {
|
||||
|
||||
@NotNull String getTableName();
|
||||
|
||||
/**
|
||||
* 选定用于查询的列名
|
||||
*
|
||||
* @param columnNames 列名
|
||||
* @return {@link TableQueryBuilder}
|
||||
*/
|
||||
TableQueryBuilder selectColumns(@NotNull String... columnNames);
|
||||
|
||||
/**
|
||||
* 对结果进行排序
|
||||
*
|
||||
* @param columnName 排序使用的列名
|
||||
* @param asc 是否为正序排序 (为false则倒序排序)
|
||||
* @return {@link TableQueryBuilder}
|
||||
*/
|
||||
TableQueryBuilder orderBy(@NotNull String columnName, boolean asc);
|
||||
|
||||
/**
|
||||
* 限制查询条数,用于分页查询。
|
||||
*
|
||||
* @param start 开始数
|
||||
* @param end 结束条数
|
||||
* @return {@link TableQueryBuilder}
|
||||
* @since 0.2.6
|
||||
*/
|
||||
TableQueryBuilder setPageLimit(int start, int end);
|
||||
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public interface UpdateBuilder extends ConditionalBuilder<UpdateBuilder, SQLAction<Integer>> {
|
||||
|
||||
String getTableName();
|
||||
|
||||
/**
|
||||
* 添加一条需要更新的字段名与值
|
||||
*
|
||||
* @param columnName 字段名
|
||||
* @param columnValue 字段名对应的值
|
||||
* @return {@link UpdateBuilder}
|
||||
* @since 0.3.7
|
||||
*/
|
||||
UpdateBuilder addColumnValue(@NotNull String columnName, @Nullable Object columnValue);
|
||||
|
||||
/**
|
||||
* 设定更新的全部字段值 <b>(此操作会覆盖之前的设定)</b>
|
||||
* <p> <b>此操作会覆盖之前的设定</b>
|
||||
*
|
||||
* @param columnData 字段名和值的键值对
|
||||
* @return {@link UpdateBuilder}
|
||||
*/
|
||||
UpdateBuilder setColumnValues(LinkedHashMap<@NotNull String, @Nullable Object> columnData);
|
||||
|
||||
/**
|
||||
* 设定更新的全部字段值 <b>(此操作会覆盖之前的设定)</b>
|
||||
* <p> <b>此操作会覆盖之前的设定</b>
|
||||
*
|
||||
* @param columnNames 字段名
|
||||
* @param columnValues 字段名对应的值
|
||||
* @return {@link UpdateBuilder}
|
||||
*/
|
||||
UpdateBuilder setColumnValues(@NotNull String[] columnNames, @Nullable Object[] columnValues);
|
||||
|
||||
/**
|
||||
* 设定更新的全部字段值 <b>(此操作会覆盖之前的设定)</b>
|
||||
* <p> 如需同时更新多条字段,请使用 {@link #setColumnValues(String[], Object[])} 或 {@link #setColumnValues(LinkedHashMap)}
|
||||
* <br>也可以使用 {@link #addColumnValue(String, Object)} 一条条的添加字段
|
||||
*
|
||||
* @param columnName 字段名
|
||||
* @param columnValue 字段名对应的值
|
||||
* @return {@link UpdateBuilder}
|
||||
*/
|
||||
default UpdateBuilder setColumnValues(@NotNull String columnName, @Nullable Object columnValue) {
|
||||
return setColumnValues(new String[]{columnName}, new Object[]{columnValue});
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.builder;
|
||||
|
||||
/**
|
||||
* 存在则更新,不存在则插入。
|
||||
*
|
||||
* @see ReplaceBuilder
|
||||
*/
|
||||
@Deprecated
|
||||
public interface UpsertBuilder {
|
||||
|
||||
String getTableName();
|
||||
|
||||
default UpsertBuilder setColumnNames(String[] columnNames, String updateColumn) {
|
||||
throw new UnsupportedOperationException("Please use REPLACE .");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.enums;
|
||||
|
||||
public enum ForeignKeyRule {
|
||||
|
||||
/**
|
||||
* 啥也不做
|
||||
* <p>注意: 在Mysql中该选项实际上等同于采用默认的 {@link #RESTRICT} 设定!
|
||||
*/
|
||||
NO_ACTION("NO ACTION"),
|
||||
|
||||
/**
|
||||
* 拒绝删除要求,直到使用删除键值的辅助表被手工删除,并且没有参照时(这是默认设置,也是最安全的设置)
|
||||
*/
|
||||
RESTRICT("RESTRICT"),
|
||||
|
||||
/**
|
||||
* 修改包含与已删除键值有参照关系的所有记录,使用NULL值替换(只能用于已标记为NOT NULL的字段)
|
||||
*/
|
||||
SET_NULL("SET NULL"),
|
||||
|
||||
/**
|
||||
* 修改包含与已删除键值有参照关系的所有记录,使用默认值替换(只能用于设定了DEFAULT的字段)
|
||||
*/
|
||||
SET_DEFAULT("SET DEFAULT"),
|
||||
|
||||
/**
|
||||
* <b>级联删除</b>,删除包含与已删除键值有参照关系的所有记录
|
||||
*/
|
||||
CASCADE("CASCADE");
|
||||
|
||||
final String ruleName;
|
||||
|
||||
ForeignKeyRule(String ruleName) {
|
||||
this.ruleName = ruleName;
|
||||
}
|
||||
|
||||
public String getRuleName() {
|
||||
return ruleName;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.enums;
|
||||
|
||||
public enum IndexType {
|
||||
|
||||
|
||||
/**
|
||||
* <b>普通索引</b>(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。
|
||||
* <br> 因此,应该只为那些最经常出现在查询条件(WHERE column=)或排序条件(ORDER BY column)中的数据列创建索引。
|
||||
* <br> 只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
|
||||
*/
|
||||
INDEX("INDEX"),
|
||||
|
||||
|
||||
/**
|
||||
* <b>唯一索引</b> 是在表上一个或者多个字段组合建立的索引,这个或者这些字段的值组合起来在表中不可以重复,用于保证数据的唯一性。
|
||||
*/
|
||||
UNIQUE_KEY("UNIQUE KEY"),
|
||||
|
||||
/**
|
||||
* <b>主键索引</b> 是唯一索引的特定类型。表中创建主键时自动创建的索引 。一个表只能建立一个主索引。
|
||||
*/
|
||||
PRIMARY_KEY("PRIMARY KEY"),
|
||||
|
||||
/**
|
||||
* <b>全文索引</b> 主要用来查找文本中的关键字,而不是直接与索引中的值相比较。
|
||||
* <br> 请搭配 MATCH 等语句使用,而不是使用 WHERE - LIKE 。
|
||||
* <br> 全文索引只可用于 CHAR、 VARCHAR 与 TEXT 系列类型。
|
||||
*/
|
||||
FULLTEXT_INDEX("FULLTEXT");
|
||||
|
||||
|
||||
final String name;
|
||||
|
||||
IndexType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.enums;
|
||||
|
||||
public enum NumberType {
|
||||
|
||||
TINYINT,
|
||||
SMALLINT,
|
||||
MEDIUMINT,
|
||||
INT,
|
||||
BIGINT
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.function;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SQLBiFunction<T, U, R> {
|
||||
|
||||
@Nullable
|
||||
R apply(@NotNull T t, @NotNull U u) throws SQLException;
|
||||
|
||||
default <V> SQLBiFunction<T, U, V> then(@NotNull SQLFunction<? super R, ? extends V> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (T t, U u) -> {
|
||||
R r = apply(t, u);
|
||||
if (r == null) return null;
|
||||
else return after.apply(r);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.function;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLQuery;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 异常处理器。
|
||||
* <br> 在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时,
|
||||
* 如果发生异常,则会调用错误处理器进行错误内容的输出提示。
|
||||
*/
|
||||
|
||||
public interface SQLDebugHandler {
|
||||
/**
|
||||
* 该方法将在 {@link SQLAction#execute()} 执行前调用。
|
||||
*
|
||||
* @param action {@link SQLAction} 对象
|
||||
* @param params 执行传入的参数列表。
|
||||
* 实际上,仅有 {@link PreparedSQLUpdateAction} 和 {@link PreparedSQLUpdateBatchAction} 才会有传入参数。
|
||||
*/
|
||||
void beforeExecute(@NotNull SQLAction<?> action, @NotNull List<@Nullable Object[]> params);
|
||||
|
||||
/**
|
||||
* 该方法将在 {@link SQLQuery#close()} 执行后调用。
|
||||
*
|
||||
* @param query {@link SQLQuery} 对象
|
||||
* @param executeNanoTime 该次查询开始执行的时间 (单位:纳秒)
|
||||
* @param closeNanoTime 该次查询彻底关闭的时间 (单位:纳秒)
|
||||
*/
|
||||
void afterQuery(@NotNull SQLQuery query, long executeNanoTime, long closeNanoTime);
|
||||
|
||||
default String parseParams(@Nullable Object[] params) {
|
||||
if (params == null) return "<#NULL>";
|
||||
else if (params.length == 0) return "<#EMPTY>";
|
||||
|
||||
List<String> paramsString = new ArrayList<>();
|
||||
for (Object param : params) {
|
||||
if (param == null) paramsString.add("NULL");
|
||||
else paramsString.add(param.toString());
|
||||
}
|
||||
return String.join(", ", paramsString);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
static SQLDebugHandler defaultHandler(Logger logger) {
|
||||
return new SQLDebugHandler() {
|
||||
|
||||
@Override
|
||||
public void beforeExecute(@NotNull SQLAction<?> action, @NotNull List<@Nullable Object[]> params) {
|
||||
logger.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
logger.info("┣# ActionUUID: {}", action.getActionUUID());
|
||||
logger.info("┣# ActionType: {}", action.getClass().getSimpleName());
|
||||
if (action.getSQLContents().size() == 1) {
|
||||
logger.info("┣# SQLContent: {}", action.getSQLContents().get(0));
|
||||
} else {
|
||||
logger.info("┣# SQLContents: ");
|
||||
int i = 0;
|
||||
for (String sqlContent : action.getSQLContents()) {
|
||||
logger.info("┃ - [{}] {}", ++i, sqlContent);
|
||||
}
|
||||
}
|
||||
if (params.size() == 1) {
|
||||
Object[] param = params.get(0);
|
||||
if (param != null) {
|
||||
logger.info("┣# SQLParam: {}", parseParams(param));
|
||||
}
|
||||
} else if (params.size() > 1) {
|
||||
logger.info("┣# SQLParams: ");
|
||||
int i = 0;
|
||||
for (Object[] param : params) {
|
||||
logger.info("┃ - [{}] {}", ++i, parseParams(param));
|
||||
}
|
||||
}
|
||||
logger.info("┣# CreateTime: {}", action.getCreateTime(TimeUnit.MILLISECONDS));
|
||||
logger.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterQuery(@NotNull SQLQuery query, long executeNanoTime, long closeNanoTime) {
|
||||
logger.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
logger.info("┣# ActionUUID: {}", query.getAction().getActionUUID());
|
||||
logger.info("┣# SQLContent: {}", query.getSQLContent());
|
||||
logger.info("┣# CloseTime: {} (cost {} ms)",
|
||||
TimeUnit.NANOSECONDS.toMillis(closeNanoTime),
|
||||
((double) (closeNanoTime - executeNanoTime) / 1000000)
|
||||
);
|
||||
logger.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.function;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* 异常处理器。
|
||||
* <br> 在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时,
|
||||
* 如果发生异常,则会调用错误处理器进行错误内容的输出提示。
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SQLExceptionHandler extends BiConsumer<SQLException, SQLAction<?>> {
|
||||
|
||||
/**
|
||||
* 默认的异常处理器,将详细的输出相关错误与错误来源。
|
||||
*
|
||||
* @param logger 用于输出错误信息的Logger。
|
||||
* @return 输出详细信息的错误处理器。
|
||||
*/
|
||||
static SQLExceptionHandler detailed(Logger logger) {
|
||||
return (exception, sqlAction) -> {
|
||||
logger.error("Error occurred while executing SQL: ");
|
||||
int i = 1;
|
||||
for (String content : sqlAction.getSQLContents()) {
|
||||
logger.error(String.format("#%d {%s}", i, content));
|
||||
i++;
|
||||
}
|
||||
exception.printStackTrace();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* “安静“ 的错误处理器,发生错误什么都不做。
|
||||
* 强烈不建议把此处理器作为默认处理器使用!
|
||||
*
|
||||
* @return 无输出的处理器。
|
||||
*/
|
||||
static SQLExceptionHandler silent() {
|
||||
return (exception, sqlAction) -> {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.function;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SQLFunction<T, R> {
|
||||
|
||||
@Nullable
|
||||
R apply(@NotNull T t) throws SQLException;
|
||||
|
||||
default <V> SQLFunction<V, R> compose(@NotNull SQLFunction<? super V, ? extends T> before) {
|
||||
Objects.requireNonNull(before);
|
||||
return (V v) -> {
|
||||
T t = before.apply(v);
|
||||
if (t == null) return null;
|
||||
else return apply(t);
|
||||
};
|
||||
}
|
||||
|
||||
default <V> SQLFunction<T, V> then(@NotNull SQLFunction<? super R, ? extends V> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (T t) -> {
|
||||
R r = apply(t);
|
||||
if (r == null) return null;
|
||||
else return after.apply(r);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.function;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SQLHandler<T> {
|
||||
|
||||
void accept(@NotNull T t) throws SQLException;
|
||||
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
default SQLHandler<T> andThen(@NotNull SQLHandler<? super T> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (T t) -> {
|
||||
accept(t);
|
||||
after.accept(t);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.table;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLManager;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
|
||||
public abstract class NamedSQLTable implements SQLTable {
|
||||
|
||||
private final @NotNull String tableName;
|
||||
|
||||
protected @Nullable String tablePrefix;
|
||||
protected @Nullable SQLManager manager;
|
||||
|
||||
/**
|
||||
* 请调用 {@link NamedSQLTable} 下的静态方法进行对象的初始化。
|
||||
*
|
||||
* @param tableName 该表的名称
|
||||
*/
|
||||
public NamedSQLTable(@NotNull String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public @NotNull String getTableName() {
|
||||
return (tablePrefix != null ? tablePrefix : "") + tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SQLManager getSQLManager() {
|
||||
return this.manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用指定 SQLManager 进行本示例的初始化。
|
||||
*
|
||||
* @param sqlManager {@link SQLManager}
|
||||
* @param tablePrefix 表名前缀
|
||||
* @return 本表是否为首次创建
|
||||
* @throws SQLException 出现任何错误时抛出
|
||||
*/
|
||||
public abstract boolean create(@NotNull SQLManager sqlManager, @Nullable String tablePrefix) throws SQLException;
|
||||
|
||||
public boolean create(@NotNull SQLManager sqlManager) throws SQLException {
|
||||
return create(sqlManager, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.util;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class TimeDateUtils {
|
||||
public static final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public TimeDateUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到当前时间文本。
|
||||
*
|
||||
* @return 时间文本 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static String getCurrentTime() {
|
||||
return getTimeString(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到一个时间戳的文本
|
||||
*
|
||||
* @param timeMillis 时间戳
|
||||
* @return 时间文本 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static String getTimeString(long timeMillis) {
|
||||
return getFormat().format(new Date(timeMillis));
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到一个日期时间的文本
|
||||
*
|
||||
* @param time 日期时间
|
||||
* @return 时间文本 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static String getTimeString(Date time) {
|
||||
return getFormat().format(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到一个时间文本的时间戳
|
||||
*
|
||||
* @param timeString 时间文本
|
||||
* @return 时间戳 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static long parseTimeMillis(String timeString) {
|
||||
if (timeString == null) {
|
||||
return -1L;
|
||||
} else {
|
||||
try {
|
||||
return format.parse(timeString).getTime();
|
||||
} catch (ParseException var2) {
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 得到一个时间文本的对应日期实例
|
||||
*
|
||||
* @param timeString 时间文本
|
||||
* @return 日期实例 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static Date getTimeDate(String timeString) {
|
||||
if (timeString == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
return format.parse(timeString);
|
||||
} catch (ParseException var2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将秒数转化为 DD:hh:mm:ss 格式
|
||||
*
|
||||
* @param allSeconds 秒数
|
||||
* @return DD:hh:mm:ss格式文本
|
||||
*/
|
||||
public static String toDHMSStyle(long allSeconds) {
|
||||
long days = allSeconds / 86400L;
|
||||
long hours = allSeconds % 86400L / 3600L;
|
||||
long minutes = allSeconds % 3600L / 60L;
|
||||
long seconds = allSeconds % 60L;
|
||||
String DateTimes;
|
||||
if (days > 0L) {
|
||||
DateTimes = days + "天" + (hours > 0L ? hours + "小时" : "") + (minutes > 0L ? minutes + "分钟" : "") + (seconds > 0L ? seconds + "秒" : "");
|
||||
} else if (hours > 0L) {
|
||||
DateTimes = hours + "小时" + (minutes > 0L ? minutes + "分钟" : "") + (seconds > 0L ? seconds + "秒" : "");
|
||||
} else if (minutes > 0L) {
|
||||
DateTimes = minutes + "分钟" + (seconds > 0L ? seconds + "秒" : "");
|
||||
} else {
|
||||
DateTimes = seconds + "秒";
|
||||
}
|
||||
|
||||
return DateTimes;
|
||||
}
|
||||
|
||||
public static DateFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.api.util;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class UUIDUtil {
|
||||
|
||||
private static final Pattern COMPILE = Pattern.compile("-", Pattern.LITERAL);
|
||||
|
||||
public static UUID random() {
|
||||
return UUID.randomUUID();
|
||||
}
|
||||
|
||||
public static String toString(UUID uuid, boolean withDash) {
|
||||
if (withDash) return uuid.toString();
|
||||
else return COMPILE.matcher(uuid.toString()).replaceAll(Matcher.quoteReplacement(""));
|
||||
}
|
||||
|
||||
public static UUID toUUID(String s) {
|
||||
if (s.length() == 36) {
|
||||
return UUID.fromString(s);
|
||||
} else {
|
||||
return UUID.fromString(s.substring(0, 8) + '-' + s.substring(8, 12) + '-' + s.substring(12, 16) + '-' + s.substring(16, 20) + '-' + s.substring(20));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractSQLBuilder implements SQLBuilder {
|
||||
|
||||
@NotNull
|
||||
final SQLManagerImpl sqlManager;
|
||||
|
||||
public AbstractSQLBuilder(@NotNull SQLManagerImpl manager) {
|
||||
Objects.requireNonNull(manager, "SQLManager must not be null");
|
||||
this.sqlManager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SQLManagerImpl getManager() {
|
||||
return this.sqlManager;
|
||||
}
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.ConditionalBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.AbstractSQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
|
||||
public abstract class AbstractConditionalBuilder<B extends ConditionalBuilder<B, T>, T extends SQLAction<?>>
|
||||
extends AbstractSQLBuilder implements ConditionalBuilder<B, T> {
|
||||
|
||||
ArrayList<String> conditionSQLs = new ArrayList<>();
|
||||
ArrayList<Object> conditionParams = new ArrayList<>();
|
||||
int limit = -1;
|
||||
|
||||
public AbstractConditionalBuilder(@NotNull SQLManagerImpl manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
protected abstract B getThis();
|
||||
|
||||
@Override
|
||||
public B setConditions(@Nullable String condition) {
|
||||
this.conditionSQLs = new ArrayList<>();
|
||||
this.conditionParams = new ArrayList<>();
|
||||
if (condition != null) this.conditionSQLs.add(condition);
|
||||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public B setConditions(
|
||||
LinkedHashMap<@NotNull String, @Nullable Object> conditions
|
||||
) {
|
||||
conditions.forEach(this::addCondition);
|
||||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public B addCondition(@Nullable String condition) {
|
||||
this.conditionSQLs.add(condition);
|
||||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public B addCondition(@NotNull String columnName, @Nullable Object queryValue) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
if (queryValue == null) {
|
||||
return addCondition(withBackQuote(columnName) + " IS NULL");
|
||||
} else {
|
||||
return addCondition(columnName, "=", queryValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public B addCondition(
|
||||
@NotNull String columnName, @NotNull String operator, @Nullable Object queryValue
|
||||
) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
Objects.requireNonNull(operator, "operator could not be null (e.g. > or = or <) ");
|
||||
addCondition(withBackQuote(columnName) + " " + operator + " ?");
|
||||
this.conditionParams.add(queryValue);
|
||||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public B addCondition(
|
||||
@NotNull String[] columnNames, @Nullable Object[] queryValues
|
||||
) {
|
||||
Objects.requireNonNull(columnNames, "columnName could not be null");
|
||||
if (queryValues == null || columnNames.length != queryValues.length) {
|
||||
throw new RuntimeException("queryNames are not match with queryValues");
|
||||
}
|
||||
for (int i = 0; i < columnNames.length; i++) {
|
||||
addCondition(columnNames[i], queryValues[i]);
|
||||
}
|
||||
return getThis();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public B addNotNullCondition(@NotNull String columnName) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
return addCondition(withBackQuote(columnName) + " IS NOT NULL");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public B addTimeCondition(
|
||||
@NotNull String columnName, @Nullable Date startDate, @Nullable Date endDate
|
||||
) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
if (startDate == null && endDate == null) return getThis(); // 都不限定时间,不用判断了
|
||||
if (startDate != null) {
|
||||
addCondition(withBackQuote(columnName) + " BETWEEN ? AND ?");
|
||||
this.conditionParams.add(startDate);
|
||||
if (endDate != null) {
|
||||
this.conditionParams.add(endDate);
|
||||
} else {
|
||||
if (startDate instanceof java.sql.Date) {
|
||||
this.conditionParams.add(new java.sql.Date(System.currentTimeMillis()));
|
||||
} else if (startDate instanceof Time) {
|
||||
this.conditionParams.add(new Time(System.currentTimeMillis()));
|
||||
} else {
|
||||
this.conditionParams.add(new Timestamp(System.currentTimeMillis()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addCondition(columnName, "<=", endDate);
|
||||
}
|
||||
return getThis();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public B setLimit(int limit) {
|
||||
this.limit = limit;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
protected String buildConditionSQL() {
|
||||
|
||||
if (!conditionSQLs.isEmpty()) {
|
||||
StringBuilder conditionBuilder = new StringBuilder();
|
||||
conditionBuilder.append("WHERE").append(" ");
|
||||
Iterator<String> iterator = conditionSQLs.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
conditionBuilder.append(iterator.next());
|
||||
if (iterator.hasNext()) conditionBuilder.append(" AND ");
|
||||
}
|
||||
return conditionBuilder.toString().trim();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String buildLimitSQL() {
|
||||
return limit > 0 ? "LIMIT " + limit : "";
|
||||
}
|
||||
|
||||
protected ArrayList<Object> getConditionParams() {
|
||||
return conditionParams;
|
||||
}
|
||||
|
||||
protected boolean hasConditions() {
|
||||
return this.conditionSQLs != null && !this.conditionSQLs.isEmpty();
|
||||
}
|
||||
|
||||
protected boolean hasConditionParams() {
|
||||
return hasConditions() && getConditionParams() != null && !getConditionParams().isEmpty();
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.PreparedSQLUpdateActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.DeleteBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
|
||||
public class DeleteBuilderImpl
|
||||
extends AbstractConditionalBuilder<DeleteBuilder, SQLAction<Integer>>
|
||||
implements DeleteBuilder {
|
||||
|
||||
protected final String tableName;
|
||||
|
||||
public DeleteBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
|
||||
super(manager);
|
||||
Objects.requireNonNull(tableName);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedSQLUpdateAction<Integer> build() {
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
|
||||
sqlBuilder.append("DELETE FROM ").append(withBackQuote(getTableName()));
|
||||
|
||||
if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL());
|
||||
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
|
||||
|
||||
return new PreparedSQLUpdateActionImpl<>(
|
||||
getManager(), Integer.class, sqlBuilder.toString(),
|
||||
(hasConditionParams() ? getConditionParams() : null)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected DeleteBuilderImpl getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.InsertBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.AbstractSQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
|
||||
public abstract class InsertBuilderImpl<T extends SQLAction<?>>
|
||||
extends AbstractSQLBuilder implements InsertBuilder<T> {
|
||||
|
||||
protected final String tableName;
|
||||
protected boolean ignore;
|
||||
|
||||
public InsertBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) {
|
||||
super(manager);
|
||||
Objects.requireNonNull(tableName);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnore() {
|
||||
return ignore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertBuilder<T> setIgnore(boolean ignore) {
|
||||
this.ignore = ignore;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected static String buildSQL(String tableName, boolean ignore, List<String> columnNames) {
|
||||
return buildSQL("INSERT "+(ignore ? "IGNORE " : "")+"INTO", tableName, columnNames);
|
||||
}
|
||||
|
||||
protected static String buildSQL(String sqlPrefix, String tableName, List<String> columnNames) {
|
||||
int valueLength = columnNames.size();
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
|
||||
sqlBuilder.append(sqlPrefix).append(" ").append(withBackQuote(tableName)).append("(");
|
||||
Iterator<String> iterator = columnNames.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
sqlBuilder.append(withBackQuote(iterator.next()));
|
||||
if (iterator.hasNext()) sqlBuilder.append(", ");
|
||||
}
|
||||
|
||||
sqlBuilder.append(") VALUES (");
|
||||
|
||||
for (int i = 0; i < valueLength; i++) {
|
||||
sqlBuilder.append("?");
|
||||
if (i != valueLength - 1) {
|
||||
sqlBuilder.append(", ");
|
||||
}
|
||||
}
|
||||
sqlBuilder.append(")");
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.query.PreparedQueryActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.action.query.QueryActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.PreparedQueryAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.QueryAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.QueryBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.TableQueryBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.AbstractSQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class QueryBuilderImpl extends AbstractSQLBuilder implements QueryBuilder {
|
||||
public QueryBuilderImpl(@NotNull SQLManagerImpl manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public QueryAction withSQL(@NotNull String sql) {
|
||||
Objects.requireNonNull(sql, "sql could not be null");
|
||||
return new QueryActionImpl(getManager(), sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedQueryAction withPreparedSQL(@NotNull String sql) {
|
||||
Objects.requireNonNull(sql, "sql could not be null");
|
||||
return new PreparedQueryActionImpl(getManager(), sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableQueryBuilder inTable(@NotNull String tableName) {
|
||||
Objects.requireNonNull(tableName, "tableName could not be null");
|
||||
return new TableQueryBuilderImpl(getManager(), tableName);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.ReplaceBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.AbstractSQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ReplaceBuilderImpl<T extends SQLAction<?>>
|
||||
extends AbstractSQLBuilder implements ReplaceBuilder<T> {
|
||||
|
||||
protected final @NotNull String tableName;
|
||||
|
||||
public ReplaceBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
|
||||
super(manager);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
protected static String buildSQL(String tableName, List<String> columnNames) {
|
||||
return InsertBuilderImpl.buildSQL("REPLACE INTO", tableName, columnNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.SQLUpdateActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.TableAlterBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.IndexType;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.AbstractSQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withQuote;
|
||||
|
||||
public class TableAlterBuilderImpl extends AbstractSQLBuilder implements TableAlterBuilder {
|
||||
|
||||
protected final @NotNull String tableName;
|
||||
|
||||
public TableAlterBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
|
||||
super(manager);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public @NotNull String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> renameTo(@NotNull String newTableName) {
|
||||
Objects.requireNonNull(newTableName, "table name could not be null");
|
||||
return createAction("ALTER TABLE " + withBackQuote(tableName) + " RENAME TO " + withBackQuote(newTableName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> changeComment(@NotNull String newTableComment) {
|
||||
Objects.requireNonNull(newTableComment, "table comment could not be null");
|
||||
return createAction("ALTER TABLE " + withBackQuote(getTableName()) + " COMMENT " + withQuote(newTableComment));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> setAutoIncrementIndex(int index) {
|
||||
return createAction("ALTER TABLE " + withBackQuote(getTableName()) + " AUTO_INCREMENT=" + index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> addIndex(@NotNull IndexType indexType, @Nullable String indexName,
|
||||
@NotNull String columnName, @NotNull String... moreColumns) {
|
||||
Objects.requireNonNull(indexType, "indexType could not be null");
|
||||
Objects.requireNonNull(columnName, "column names could not be null");
|
||||
Objects.requireNonNull(moreColumns, "column names could not be null");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " ADD "
|
||||
+ TableCreateBuilderImpl.buildIndexSettings(indexType, indexName, columnName, moreColumns)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> dropIndex(@NotNull String indexName) {
|
||||
Objects.requireNonNull(indexName, "indexName could not be null");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP INDEX " + withBackQuote(indexName)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> dropForeignKey(@NotNull String keySymbol) {
|
||||
Objects.requireNonNull(keySymbol, "keySymbol could not be null");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP FOREIGN KEY " + withBackQuote(keySymbol)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> dropPrimaryKey() {
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP PRIMARY KEY"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
Objects.requireNonNull(settings, "settings could not be null");
|
||||
String orderSettings = null;
|
||||
if (afterColumn != null) {
|
||||
if (afterColumn.length() > 0) {
|
||||
orderSettings = "AFTER " + withBackQuote(afterColumn);
|
||||
} else {
|
||||
orderSettings = "FIRST";
|
||||
}
|
||||
}
|
||||
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " ADD " + withBackQuote(columnName) + " " + settings
|
||||
+ (orderSettings != null ? " " + orderSettings : "")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> renameColumn(@NotNull String columnName, @NotNull String newName) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
Objects.requireNonNull(newName, "please specify new column name");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " RENAME COLUMN " + withBackQuote(columnName) + " TO " + withBackQuote(newName)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String settings) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
Objects.requireNonNull(settings, "please specify new column settings");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " MODIFY COLUMN " + withBackQuote(columnName) + " " + settings
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> removeColumn(@NotNull String columnName) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP " + withBackQuote(columnName)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> setColumnDefault(@NotNull String columnName, @NotNull String defaultValue) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
Objects.requireNonNull(defaultValue, "defaultValue could not be null, if you need to remove the default value, please use #removeColumnDefault().");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " ALTER " + withBackQuote(columnName) + " SET DEFAULT " + defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLAction<Integer> removeColumnDefault(@NotNull String columnName) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
return createAction(
|
||||
"ALTER TABLE " + withBackQuote(getTableName()) + " ALTER " + withBackQuote(columnName) + " DROP DEFAULT"
|
||||
);
|
||||
}
|
||||
|
||||
private SQLUpdateActionImpl<Integer> createAction(@NotNull String sql) {
|
||||
return new SQLUpdateActionImpl<>(getManager(), Integer.class, sql);
|
||||
}
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.SQLUpdateActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.TableCreateBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.ForeignKeyRule;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.IndexType;
|
||||
import com.io.yutian.elementoriginlib.sql.api.enums.NumberType;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.AbstractSQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withQuote;
|
||||
|
||||
public class TableCreateBuilderImpl extends AbstractSQLBuilder implements TableCreateBuilder {
|
||||
|
||||
protected final @NotNull String tableName;
|
||||
@NotNull
|
||||
final List<String> indexes = new ArrayList<>();
|
||||
@NotNull
|
||||
final List<String> foreignKeys = new ArrayList<>();
|
||||
@NotNull List<String> columns = new ArrayList<>();
|
||||
@NotNull String tableSettings = defaultTablesSettings();
|
||||
@Nullable String tableComment;
|
||||
|
||||
public TableCreateBuilderImpl(SQLManagerImpl manager, @NotNull String tableName) {
|
||||
super(manager);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
protected static String buildIndexSettings(@NotNull IndexType indexType, @Nullable String indexName,
|
||||
@NotNull String columnName, @NotNull String... moreColumns) {
|
||||
Objects.requireNonNull(indexType, "indexType could not be null");
|
||||
Objects.requireNonNull(columnName, "column names could not be null");
|
||||
Objects.requireNonNull(moreColumns, "column names could not be null");
|
||||
StringBuilder indexBuilder = new StringBuilder();
|
||||
|
||||
indexBuilder.append(indexType.getName()).append(" ");
|
||||
if (indexName != null) {
|
||||
indexBuilder.append(withBackQuote(indexName));
|
||||
}
|
||||
indexBuilder.append("(");
|
||||
indexBuilder.append(withBackQuote(columnName));
|
||||
|
||||
if (moreColumns.length > 0) {
|
||||
indexBuilder.append(", ");
|
||||
|
||||
for (int i = 0; i < moreColumns.length; i++) {
|
||||
indexBuilder.append(withBackQuote(moreColumns[i]));
|
||||
if (i != moreColumns.length - 1) indexBuilder.append(", ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
indexBuilder.append(")");
|
||||
|
||||
return indexBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTableName() {
|
||||
return this.tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTableSettings() {
|
||||
return this.tableSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLUpdateAction<Integer> build() {
|
||||
StringBuilder createSQL = new StringBuilder();
|
||||
createSQL.append("CREATE TABLE IF NOT EXISTS ").append(withBackQuote(tableName));
|
||||
createSQL.append("(");
|
||||
createSQL.append(String.join(", ", columns));
|
||||
if (indexes.size() > 0) {
|
||||
createSQL.append(", ");
|
||||
createSQL.append(String.join(", ", indexes));
|
||||
}
|
||||
if (foreignKeys.size() > 0) {
|
||||
createSQL.append(", ");
|
||||
createSQL.append(String.join(", ", foreignKeys));
|
||||
}
|
||||
createSQL.append(") ").append(getTableSettings());
|
||||
|
||||
if (tableComment != null) {
|
||||
createSQL.append(" COMMENT ").append(withQuote(tableComment));
|
||||
}
|
||||
|
||||
return new SQLUpdateActionImpl<>(getManager(), Integer.class, createSQL.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder addColumn(@NotNull String column) {
|
||||
Objects.requireNonNull(column, "column could not be null");
|
||||
this.columns.add(column);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
|
||||
boolean asPrimaryKey, boolean unsigned) {
|
||||
return addColumn(columnName,
|
||||
(numberType == null ? NumberType.INT : numberType).name()
|
||||
+ (unsigned ? " UNSIGNED " : " ")
|
||||
+ "NOT NULL AUTO_INCREMENT " + (asPrimaryKey ? "PRIMARY KEY" : "UNIQUE KEY")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder setIndex(@NotNull IndexType type, @Nullable String indexName,
|
||||
@NotNull String columnName, @NotNull String... moreColumns) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
this.indexes.add(buildIndexSettings(type, indexName, columnName, moreColumns));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
|
||||
@NotNull String foreignTable, @NotNull String foreignColumn,
|
||||
@Nullable ForeignKeyRule updateRule, @Nullable ForeignKeyRule deleteRule) {
|
||||
Objects.requireNonNull(tableColumn, "tableColumn could not be null");
|
||||
Objects.requireNonNull(foreignTable, "foreignTable could not be null");
|
||||
Objects.requireNonNull(foreignColumn, "foreignColumn could not be null");
|
||||
|
||||
StringBuilder keyBuilder = new StringBuilder();
|
||||
|
||||
keyBuilder.append("CONSTRAINT ");
|
||||
if (constraintName == null) {
|
||||
keyBuilder.append(withBackQuote("fk_" + tableColumn + "_" + foreignTable));
|
||||
} else {
|
||||
keyBuilder.append(withBackQuote(constraintName));
|
||||
}
|
||||
keyBuilder.append(" ");
|
||||
keyBuilder.append("FOREIGN KEY (").append(withBackQuote(tableColumn)).append(") ");
|
||||
keyBuilder.append("REFERENCES ").append(withBackQuote(foreignTable)).append("(").append(withBackQuote(foreignColumn)).append(")");
|
||||
|
||||
if (updateRule != null) keyBuilder.append(" ON UPDATE ").append(updateRule.getRuleName());
|
||||
if (deleteRule != null) keyBuilder.append(" ON DELETE ").append(deleteRule.getRuleName());
|
||||
|
||||
this.foreignKeys.add(keyBuilder.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder setColumns(@NotNull String... columns) {
|
||||
Objects.requireNonNull(columns, "columns could not be null");
|
||||
this.columns = Arrays.asList(columns);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder setTableSettings(@NotNull String settings) {
|
||||
Objects.requireNonNull(settings, "settings could not be null");
|
||||
this.tableSettings = settings;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder setTableComment(@Nullable String comment) {
|
||||
this.tableComment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.TableMetadataBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLBiFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.AbstractSQLBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class TableMetadataBuilderImpl
|
||||
extends AbstractSQLBuilder
|
||||
implements TableMetadataBuilder {
|
||||
|
||||
protected final @NotNull String tablePattern;
|
||||
|
||||
public TableMetadataBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tablePattern) {
|
||||
super(manager);
|
||||
this.tablePattern = tablePattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> validateExist() {
|
||||
return validate((meta, conn) -> meta.getTables(conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(), new String[]{"TABLE"}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> CompletableFuture<R> fetchColumns(@Nullable String columnPattern,
|
||||
@NotNull SQLFunction<ResultSet, R> reader) {
|
||||
return getManager().fetchMetadata((meta, conn) -> meta.getColumns(
|
||||
conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(),
|
||||
Optional.ofNullable(columnPattern).map(String::toUpperCase).orElse("%")
|
||||
), reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> isColumnExists(@NotNull String columnPattern) {
|
||||
return validate((meta, conn) -> meta.getColumns(
|
||||
conn.getCatalog(), conn.getSchema(),
|
||||
tablePattern.toUpperCase(), columnPattern.toUpperCase()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Set<String>> listColumns(@Nullable String columnPattern) {
|
||||
return fetchColumns(columnPattern, (rs) -> {
|
||||
Set<String> data = new LinkedHashSet<>();
|
||||
while (rs.next()) {
|
||||
data.add(rs.getString("COLUMN_NAME"));
|
||||
}
|
||||
return Collections.unmodifiableSet(data);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* fast validate EXISTS.
|
||||
*
|
||||
* @param supplier supplier to get result set
|
||||
* @return result future
|
||||
*/
|
||||
private CompletableFuture<Boolean> validate(SQLBiFunction<DatabaseMetaData, Connection, ResultSet> supplier) {
|
||||
return getManager().fetchMetadata(supplier, ResultSet::next);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.query.PreparedQueryActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.query.PreparedQueryAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.TableQueryBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
|
||||
public class TableQueryBuilderImpl
|
||||
extends AbstractConditionalBuilder<TableQueryBuilder, PreparedQueryAction>
|
||||
implements TableQueryBuilder {
|
||||
|
||||
|
||||
protected final @NotNull String tableName;
|
||||
|
||||
String[] columns;
|
||||
|
||||
@Nullable String orderBy;
|
||||
|
||||
int[] pageLimit;
|
||||
|
||||
public TableQueryBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
|
||||
super(manager);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedQueryActionImpl build() {
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT").append(" ");
|
||||
if (columns == null || columns.length < 1) {
|
||||
sqlBuilder.append("*");
|
||||
} else {
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
String name = columns[i];
|
||||
sqlBuilder.append(withBackQuote(name));
|
||||
if (i != columns.length - 1) {
|
||||
sqlBuilder.append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlBuilder.append(" ").append("FROM").append(" ").append(withBackQuote(tableName));
|
||||
|
||||
if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL());
|
||||
|
||||
if (orderBy != null) sqlBuilder.append(" ").append(orderBy);
|
||||
|
||||
if (pageLimit != null && pageLimit.length == 2) {
|
||||
sqlBuilder.append(" LIMIT ").append(pageLimit[0]).append(",").append(pageLimit[1]);
|
||||
} else if (limit > 0) {
|
||||
sqlBuilder.append(" ").append(buildLimitSQL());
|
||||
}
|
||||
|
||||
|
||||
return new PreparedQueryActionImpl(getManager(), sqlBuilder.toString())
|
||||
.setParams(hasConditionParams() ? getConditionParams() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableQueryBuilderImpl selectColumns(@NotNull String... columnNames) {
|
||||
Objects.requireNonNull(columnNames, "columnNames could not be null");
|
||||
this.columns = columnNames;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableQueryBuilder orderBy(@NotNull String columnName, boolean asc) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
this.orderBy = "ORDER BY " + withBackQuote(columnName) + " " + (asc ? "ASC" : "DESC");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableQueryBuilder setPageLimit(int start, int end) {
|
||||
this.pageLimit = new int[]{start, end};
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TableQueryBuilderImpl getThis() {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.builder.impl;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.PreparedSQLUpdateActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.UpdateBuilder;
|
||||
import com.io.yutian.elementoriginlib.sql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.io.yutian.elementoriginlib.sql.api.SQLBuilder.withBackQuote;
|
||||
|
||||
public class UpdateBuilderImpl
|
||||
extends AbstractConditionalBuilder<UpdateBuilder, SQLAction<Integer>>
|
||||
implements UpdateBuilder {
|
||||
|
||||
protected final @NotNull String tableName;
|
||||
|
||||
@NotNull LinkedHashMap<String, Object> columnData;
|
||||
|
||||
public UpdateBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
|
||||
super(manager);
|
||||
this.tableName = tableName;
|
||||
this.columnData = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedSQLUpdateAction<Integer> build() {
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
|
||||
sqlBuilder.append("UPDATE ").append(withBackQuote(getTableName())).append(" SET ");
|
||||
|
||||
Iterator<String> iterator = this.columnData.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
sqlBuilder.append(withBackQuote(iterator.next())).append(" = ?");
|
||||
if (iterator.hasNext()) sqlBuilder.append(" , ");
|
||||
}
|
||||
List<Object> allParams = new ArrayList<>(this.columnData.values());
|
||||
|
||||
if (hasConditions()) {
|
||||
sqlBuilder.append(" ").append(buildConditionSQL());
|
||||
allParams.addAll(getConditionParams());
|
||||
}
|
||||
|
||||
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
|
||||
|
||||
return new PreparedSQLUpdateActionImpl<>(getManager(), Integer.class, sqlBuilder.toString(), allParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateBuilder addColumnValue(@NotNull String columnName, Object columnValue) {
|
||||
Objects.requireNonNull(columnName, "columnName could not be null");
|
||||
this.columnData.put(columnName, columnValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData) {
|
||||
this.columnData = columnData;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateBuilder setColumnValues(@NotNull String[] columnNames, @Nullable Object[] columnValues) {
|
||||
Objects.requireNonNull(columnNames, "columnName could not be null");
|
||||
if (columnNames.length != columnValues.length) {
|
||||
throw new RuntimeException("columnNames are not match with columnValues");
|
||||
}
|
||||
LinkedHashMap<String, Object> columnData = new LinkedHashMap<>();
|
||||
for (int i = 0; i < columnNames.length; i++) {
|
||||
columnData.put(columnNames[i], columnValues[i]);
|
||||
}
|
||||
return setColumnValues(columnData);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected UpdateBuilder getThis() {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.manager;
|
||||
|
||||
import com.io.yutian.elementoriginlib.sql.action.PreparedSQLBatchUpdateActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.action.PreparedSQLUpdateActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.action.SQLUpdateActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.action.SQLUpdateBatchActionImpl;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLManager;
|
||||
import com.io.yutian.elementoriginlib.sql.api.SQLQuery;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.action.SQLUpdateBatchAction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.builder.*;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLBiFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLDebugHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLExceptionHandler;
|
||||
import com.io.yutian.elementoriginlib.sql.api.function.SQLFunction;
|
||||
import com.io.yutian.elementoriginlib.sql.builder.impl.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SQLManagerImpl implements SQLManager {
|
||||
|
||||
private final Logger LOGGER;
|
||||
private final DataSource dataSource;
|
||||
private final ConcurrentHashMap<UUID, SQLQuery> activeQuery = new ConcurrentHashMap<>();
|
||||
protected ExecutorService executorPool;
|
||||
@NotNull Supplier<Boolean> debugMode = () -> Boolean.FALSE;
|
||||
|
||||
@NotNull SQLExceptionHandler exceptionHandler;
|
||||
@NotNull SQLDebugHandler debugHandler;
|
||||
|
||||
public SQLManagerImpl(@NotNull DataSource dataSource) {
|
||||
this(dataSource, null);
|
||||
}
|
||||
|
||||
public SQLManagerImpl(@NotNull DataSource dataSource, @Nullable String name) {
|
||||
this(dataSource, LoggerFactory.getLogger(SQLManagerImpl.class), name);
|
||||
}
|
||||
|
||||
public SQLManagerImpl(@NotNull DataSource dataSource, @NotNull Logger logger, @Nullable String name) {
|
||||
String managerName = "SQLManager" + (name != null ? "#" + name : "");
|
||||
this.LOGGER = logger;
|
||||
this.dataSource = dataSource;
|
||||
this.executorPool = SQLManager.defaultExecutorPool(managerName);
|
||||
this.exceptionHandler = SQLExceptionHandler.detailed(getLogger());
|
||||
this.debugHandler = SQLDebugHandler.defaultHandler(getLogger());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugMode() {
|
||||
return this.debugMode.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDebugMode(@NotNull Supplier<@NotNull Boolean> debugMode) {
|
||||
this.debugMode = debugMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SQLDebugHandler getDebugHandler() {
|
||||
return this.debugHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDebugHandler(@NotNull SQLDebugHandler debugHandler) {
|
||||
this.debugHandler = debugHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return LOGGER;
|
||||
}
|
||||
|
||||
public @NotNull ExecutorService getExecutorPool() {
|
||||
return executorPool;
|
||||
}
|
||||
|
||||
public void setExecutorPool(@NotNull ExecutorService executorPool) {
|
||||
this.executorPool = executorPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DataSource getDataSource() {
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Connection getConnection() throws SQLException {
|
||||
return getDataSource().getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<UUID, SQLQuery> getActiveQuery() {
|
||||
return this.activeQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SQLExceptionHandler getExceptionHandler() {
|
||||
return this.exceptionHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExceptionHandler(@Nullable SQLExceptionHandler handler) {
|
||||
if (handler == null) this.exceptionHandler = SQLExceptionHandler.detailed(getLogger());
|
||||
else this.exceptionHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer executeSQL(String sql) {
|
||||
return new SQLUpdateActionImpl<>(this, Integer.class, sql).execute(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer executeSQL(String sql, Object[] params) {
|
||||
return new PreparedSQLUpdateActionImpl<>(this, Integer.class, sql, params).execute(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> executeSQLBatch(String sql, Iterable<Object[]> paramsBatch) {
|
||||
return new PreparedSQLBatchUpdateActionImpl<>(this, Integer.class, sql).setAllParams(paramsBatch).execute(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> executeSQLBatch(@NotNull String sql, String... moreSQL) {
|
||||
SQLUpdateBatchAction action = new SQLUpdateBatchActionImpl(this, sql);
|
||||
if (moreSQL != null && moreSQL.length > 0) {
|
||||
Arrays.stream(moreSQL).forEach(action::addBatch);
|
||||
}
|
||||
return action.execute(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch) {
|
||||
Iterator<String> iterator = sqlBatch.iterator();
|
||||
if (!iterator.hasNext()) return null; // PLEASE GIVE IT SOMETHING
|
||||
|
||||
SQLUpdateBatchAction action = new SQLUpdateBatchActionImpl(this, iterator.next());
|
||||
while (iterator.hasNext()) {
|
||||
action.addBatch(iterator.next());
|
||||
}
|
||||
|
||||
return action.execute(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, R> reader) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try (Connection conn = getConnection()) {
|
||||
return reader.apply(conn.getMetaData(), conn);
|
||||
} catch (SQLException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}, this.executorPool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, ResultSet> supplier,
|
||||
@NotNull SQLFunction<@NotNull ResultSet, R> reader) {
|
||||
return fetchMetadata((meta, conn) -> {
|
||||
try (ResultSet rs = supplier.apply(conn.getMetaData(), conn)) {
|
||||
if (rs == null) throw new NullPointerException("Metadata返回的ResultSet为null。");
|
||||
else return reader.apply(rs);
|
||||
} catch (SQLException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder createTable(@NotNull String tableName) {
|
||||
return new TableCreateBuilderImpl(this, tableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableAlterBuilder alterTable(@NotNull String tableName) {
|
||||
return new TableAlterBuilderImpl(this, tableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableMetadataBuilder fetchTableMetadata(@NotNull String tablePattern) {
|
||||
return new TableMetadataBuilderImpl(this, tablePattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryBuilder createQuery() {
|
||||
return new QueryBuilderImpl(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull String tableName) {
|
||||
return new InsertBuilderImpl<PreparedSQLUpdateBatchAction<Integer>>(this, tableName) {
|
||||
@Override
|
||||
public PreparedSQLUpdateBatchAction<Integer> setColumnNames(List<String> columnNames) {
|
||||
return new PreparedSQLBatchUpdateActionImpl<>(getManager(), Integer.class, buildSQL(getTableName(), isIgnore(), columnNames));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull String tableName) {
|
||||
return new InsertBuilderImpl<PreparedSQLUpdateAction<Integer>>(this, tableName) {
|
||||
@Override
|
||||
public PreparedSQLUpdateAction<Integer> setColumnNames(List<String> columnNames) {
|
||||
return new PreparedSQLUpdateActionImpl<>(getManager(), Integer.class, buildSQL(getTableName(), isIgnore(), columnNames));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull String tableName) {
|
||||
return new ReplaceBuilderImpl<PreparedSQLUpdateBatchAction<Integer>>(this, tableName) {
|
||||
@Override
|
||||
public PreparedSQLUpdateBatchAction<Integer> setColumnNames(List<String> columnNames) {
|
||||
return new PreparedSQLBatchUpdateActionImpl<>(getManager(), Integer.class, buildSQL(getTableName(), columnNames));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull String tableName) {
|
||||
return new ReplaceBuilderImpl<PreparedSQLUpdateAction<Integer>>(this, tableName) {
|
||||
@Override
|
||||
public PreparedSQLUpdateAction<Integer> setColumnNames(List<String> columnNames) {
|
||||
return new PreparedSQLUpdateActionImpl<>(getManager(), Integer.class, buildSQL(getTableName(), columnNames));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateBuilder createUpdate(@NotNull String tableName) {
|
||||
return new UpdateBuilderImpl(this, tableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteBuilder createDelete(@NotNull String tableName) {
|
||||
return new DeleteBuilderImpl(this, tableName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.util;
|
||||
|
||||
public enum DatabaseDriverType {
|
||||
|
||||
MYSQL("com.mysql.jdbc.Driver"),
|
||||
MYSQL_CJ("com.mysql.cj.jdbc.Driver"),
|
||||
SQLITE("org.sqlite.JDBC"),
|
||||
H2("org.h2.Driver");
|
||||
|
||||
private String driverClassName;
|
||||
|
||||
DatabaseDriverType(String driverClassName) {
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
|
||||
public String getDriverClassName() {
|
||||
return driverClassName;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.sql.util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class StatementUtil {
|
||||
|
||||
/**
|
||||
* 创建一个 {@link PreparedStatement} 。
|
||||
*
|
||||
* @param connection 数据库连接
|
||||
* @param sql SQL语句,使用"?"做为占位符
|
||||
* @param params "?"所代表的对应参数列表
|
||||
* @return 完成参数填充的 {@link PreparedStatement}
|
||||
*/
|
||||
public static PreparedStatement createPrepareStatement(
|
||||
Connection connection, String sql, Object[] params
|
||||
) throws SQLException {
|
||||
return createPrepareStatement(connection, sql, params, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个 {@link PreparedStatement} 。
|
||||
*
|
||||
* @param connection 数据库连接
|
||||
* @param sql SQL语句,使用"?"做为占位符
|
||||
* @param params "?"所代表的对应参数列表
|
||||
* @param returnGeneratedKey 是否会返回自增主键
|
||||
* @return 完成参数填充的 {@link PreparedStatement}
|
||||
*/
|
||||
public static PreparedStatement createPrepareStatement(
|
||||
Connection connection, String sql, Object[] params, boolean returnGeneratedKey
|
||||
) throws SQLException {
|
||||
sql = sql.trim();
|
||||
PreparedStatement statement = connection.prepareStatement(sql, returnGeneratedKey ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS);
|
||||
Map<Integer, Integer> nullTypeMap = new HashMap<>();
|
||||
if (params != null) fillParams(statement, Arrays.asList(params), nullTypeMap);
|
||||
statement.addBatch();
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建批量操作的一个 {@link PreparedStatement} 。
|
||||
*
|
||||
* @param connection 数据库连接
|
||||
* @param sql SQL语句,使用"?"做为占位符
|
||||
* @param paramsBatch "?"所代表的对应参数列表
|
||||
* @return 完成参数填充的 {@link PreparedStatement}
|
||||
*/
|
||||
public static PreparedStatement createPrepareStatementBatch(
|
||||
Connection connection, String sql, Iterable<Object[]> paramsBatch
|
||||
) throws SQLException {
|
||||
return createPrepareStatementBatch(connection, sql, paramsBatch, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建批量操作的一个 {@link PreparedStatement} 。
|
||||
*
|
||||
* @param connection 数据库连接
|
||||
* @param sql SQL语句,使用"?"做为占位符
|
||||
* @param paramsBatch "?"所代表的对应参数列表
|
||||
* @param returnGeneratedKey 是否会返回自增主键
|
||||
* @return 完成参数填充的 {@link PreparedStatement}
|
||||
*/
|
||||
public static PreparedStatement createPrepareStatementBatch(
|
||||
Connection connection, String sql, Iterable<Object[]> paramsBatch, boolean returnGeneratedKey
|
||||
) throws SQLException {
|
||||
|
||||
sql = sql.trim();
|
||||
PreparedStatement statement = connection.prepareStatement(sql, returnGeneratedKey ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS);
|
||||
Map<Integer, Integer> nullTypeMap = new HashMap<>();
|
||||
for (Object[] params : paramsBatch) {
|
||||
fillParams(statement, Arrays.asList(params), nullTypeMap);
|
||||
statement.addBatch();
|
||||
}
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 填充PreparedStatement的参数。
|
||||
*
|
||||
* @param statement PreparedStatement
|
||||
* @param params SQL参数
|
||||
* @return {@link PreparedStatement} 填充参数后的PreparedStatement
|
||||
* @throws SQLException SQL执行异常
|
||||
*/
|
||||
public static PreparedStatement fillParams(
|
||||
PreparedStatement statement, Iterable<?> params
|
||||
) throws SQLException {
|
||||
return fillParams(statement, params, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充PreparedStatement的参数。
|
||||
*
|
||||
* @param statement PreparedStatement
|
||||
* @param params SQL参数
|
||||
* @param nullCache null参数的类型缓存,避免循环中重复获取类型
|
||||
* @return 完成参数填充的 {@link PreparedStatement}
|
||||
*/
|
||||
public static PreparedStatement fillParams(
|
||||
PreparedStatement statement, Iterable<?> params, Map<Integer, Integer> nullCache
|
||||
) throws SQLException {
|
||||
if (null == params) {
|
||||
return statement;// 无参数
|
||||
}
|
||||
|
||||
int paramIndex = 1;//第一个参数从1计数
|
||||
for (Object param : params) {
|
||||
setParam(statement, paramIndex++, param, nullCache);
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取null字段对应位置的数据类型
|
||||
* 如果类型获取失败将使用默认的 {@link Types#VARCHAR}
|
||||
*
|
||||
* @param statement {@link PreparedStatement}
|
||||
* @param paramIndex 参数序列,第一位从1开始
|
||||
* @return 数据类型,默认为 {@link Types#VARCHAR}
|
||||
*/
|
||||
public static int getNullType(PreparedStatement statement, int paramIndex) {
|
||||
try {
|
||||
ParameterMetaData pmd = statement.getParameterMetaData();
|
||||
return pmd.getParameterType(paramIndex);
|
||||
} catch (SQLException ignore) {
|
||||
return Types.VARCHAR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 {@link PreparedStatement} 设置单个参数
|
||||
*
|
||||
* @param preparedStatement {@link PreparedStatement}
|
||||
* @param paramIndex 参数序列,从1开始
|
||||
* @param param 参数,不能为{@code null}
|
||||
* @param nullCache 用于缓存参数为null位置的类型,避免重复获取
|
||||
*/
|
||||
private static void setParam(
|
||||
PreparedStatement preparedStatement, int paramIndex, Object param,
|
||||
Map<Integer, Integer> nullCache
|
||||
) throws SQLException {
|
||||
|
||||
if (param == null) {
|
||||
Integer type = (null == nullCache) ? null : nullCache.get(paramIndex);
|
||||
if (null == type) {
|
||||
type = getNullType(preparedStatement, paramIndex);
|
||||
if (null != nullCache) {
|
||||
nullCache.put(paramIndex, type);
|
||||
}
|
||||
}
|
||||
preparedStatement.setNull(paramIndex, type);
|
||||
}
|
||||
|
||||
// 针对UUID特殊处理,避免元数据直接传入
|
||||
if (param instanceof UUID) {
|
||||
preparedStatement.setString(paramIndex, param.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
// 针对StringBuilder或StringBuffer进行处理,避免元数据传入
|
||||
if (param instanceof StringBuilder || param instanceof StringBuffer) {
|
||||
preparedStatement.setString(paramIndex, param.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
// 日期特殊处理,默认按照时间戳传入,避免精度丢失
|
||||
if (param instanceof java.util.Date) {
|
||||
if (param instanceof Date) {
|
||||
preparedStatement.setDate(paramIndex, (Date) param);
|
||||
} else if (param instanceof Time) {
|
||||
preparedStatement.setTime(paramIndex, (Time) param);
|
||||
} else {
|
||||
preparedStatement.setTimestamp(paramIndex, new Timestamp(((java.util.Date) param).getTime()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 针对大数字类型的特殊处理
|
||||
if (param instanceof Number) {
|
||||
if (param instanceof BigDecimal) {
|
||||
// BigDecimal的转换交给JDBC驱动处理
|
||||
preparedStatement.setBigDecimal(paramIndex, (BigDecimal) param);
|
||||
return;
|
||||
} else if (param instanceof BigInteger) {
|
||||
preparedStatement.setBigDecimal(paramIndex, new BigDecimal((BigInteger) param));
|
||||
return;
|
||||
}
|
||||
// 其它数字类型按照默认类型传入
|
||||
}
|
||||
|
||||
if (param instanceof Enum) {
|
||||
//枚举类采用 name()
|
||||
preparedStatement.setString(paramIndex, ((Enum<?>) param).name());
|
||||
return;
|
||||
}
|
||||
|
||||
// 其它参数类型直接传入
|
||||
preparedStatement.setObject(paramIndex, param);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package com.io.yutian.elementoriginlib.util;
|
||||
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTCompound;
|
||||
import com.io.yutian.elementoriginlib.nbt.TagCompound;
|
||||
import com.io.yutian.elementoriginlib.nbt.NBTItem;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
@ -47,9 +47,9 @@ public class ItemStackUtil {
|
|||
}
|
||||
NBTItem nbtOriginal = new NBTItem(original);
|
||||
NBTItem nbtTester = new NBTItem(tester);
|
||||
NBTCompound nbtCompound0 = nbtOriginal.getTag();
|
||||
NBTCompound nbtCompound1 = nbtTester.getTag();
|
||||
return nbtCompound0.equals(nbtCompound1);
|
||||
TagCompound tagCompound0 = nbtOriginal.getTag();
|
||||
TagCompound tagCompound1 = nbtTester.getTag();
|
||||
return tagCompound0.equals(tagCompound1);
|
||||
}
|
||||
|
||||
public static int countItems(Inventory inventory, @NotNull ItemStack item) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user