Database Start

This commit is contained in:
James Peters 2021-07-28 18:36:52 +01:00
parent f9d60de527
commit 2e569ed6ac
11 changed files with 438 additions and 1 deletions

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ChestsPlusPlus-Parent</artifactId>
<groupId>com.jamesdpeters.minecraft.chests</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ChestsPlusPlus-Database</artifactId>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>maven-google</id>
<url>https://maven.google.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.5.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.5.4.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.5.4.Final</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,62 @@
package com.jamesdpeters.minecraft.database.hibernate;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
public class Database<T> {
private final Class<T> clazz;
public Database(Class<T> clazz) {
this.clazz = clazz;
}
//** MEMBER METHODS **/
public void saveEntity(Object object) {
runTransaction(entityManager -> entityManager.persist(object));
}
public Optional<T> findEntity(Object id) {
return Optional.ofNullable(HibernateUtil.getEntityManager().find(clazz, id));
}
public List<T> findAll() {
var q = HibernateUtil.getCriteriaQuery(clazz);
q.select(q.from(clazz));
return HibernateUtil.getEntityManager().createQuery(q).getResultList();
}
public List<T> findAll(String sql) {
var q = HibernateUtil.getEntityManager().createQuery(sql, clazz);
return q.getResultList();
}
public TypedQuery<T> getQuery(String sql) {
return HibernateUtil.getEntityManager().createQuery(sql, clazz);
}
public void runTransaction(Consumer<EntityManager> sessionConsumer) {
var entityManager = HibernateUtil.getEntityManager();
var transaction = entityManager.getTransaction();
try {
transaction.begin();
sessionConsumer.accept(entityManager);
transaction.commit();
} catch (RuntimeException e) {
transaction.rollback();
throw e;
}
}
public void refresh(T entity) {
HibernateUtil.getEntityManager().refresh(entity);
}
public Class<T> clazz() {
return clazz;
}
}

View File

@ -0,0 +1,76 @@
package com.jamesdpeters.minecraft.database.hibernate;
import lombok.experimental.UtilityClass;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import java.io.File;
import java.util.Arrays;
import java.util.Properties;
@UtilityClass
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static EntityManager entityManager;
private static File databaseDirectory;
private static Properties hibernateProperties() {
Properties properties = new Properties();
properties.put(Environment.DRIVER, "org.h2.Driver");
properties.put(Environment.URL, "jdbc:h2:file:"+databaseDirectory.getAbsolutePath()+"/db;AUTO_SERVER=TRUE");
properties.put(Environment.USER, "sa");
properties.put(Environment.PASS, "sa");
properties.put(Environment.FORMAT_SQL, "true");
properties.put(Environment.DIALECT, "org.hibernate.dialect.H2Dialect");
properties.put(Environment.SHOW_SQL, "true");
properties.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
properties.put(Environment.HBM2DDL_AUTO, "update");
// properties.put(Environment.POOL_SIZE, "5");
return properties;
}
private static SessionFactory buildSessionFactory(Class<?>[] entities) {
try {
var config = new Configuration()
.addProperties(hibernateProperties())
.addPackage("com.jamesdpeters.minecraft.database.entities");
Arrays.stream(entities).forEach(config::addAnnotatedClass);
return config.buildSessionFactory();
} catch (Throwable ex) {
System.err.println("build SeesionFactory failed :" + ex);
throw new ExceptionInInitializerError(ex);
}
}
public void init(File databaseDirectory, Class<?>[] entities) {
HibernateUtil.databaseDirectory = databaseDirectory;
sessionFactory = buildSessionFactory(entities);
entityManager = sessionFactory.createEntityManager();
}
public EntityManager getEntityManager() {
return entityManager;
}
public <T> CriteriaQuery<T> getCriteriaQuery(Class<T> clazz) {
return entityManager.getCriteriaBuilder().createQuery(clazz);
}
public CriteriaBuilder getCriteriaBuilder() {
return entityManager.getCriteriaBuilder();
}
public void close() {
if (sessionFactory != null)
sessionFactory.close();
if (entityManager != null)
entityManager.close();
}
}

View File

@ -154,6 +154,14 @@
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.jamesdpeters</groupId>-->
<!-- <artifactId>ChestsPlusPlus-Database</artifactId>-->
<!-- <version>0.0.1-SNAPSHOT</version>-->
<!-- <classifier>jar-with-dependencies</classifier>-->
<!-- </dependency>-->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
@ -169,6 +177,12 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.jamesdpeters.minecraft.chests</groupId>
<artifactId>ChestsPlusPlus-Database</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
@ -190,6 +204,7 @@
<include>net.wesjd:anvilgui*</include>
<include>org.bstats*:*</include>
<include>com.jamesdpeters.minecraft.chests</include>
<include>com.jamesdpeters*:*</include>
</includes>
</artifactSet>
<relocations>

View File

@ -5,6 +5,7 @@ import com.jamesdpeters.minecraft.chests.commands.AutoCraftCommand;
import com.jamesdpeters.minecraft.chests.commands.ChestLinkCommand;
import com.jamesdpeters.minecraft.chests.commands.ChestsPlusPlusCommand;
import com.jamesdpeters.minecraft.chests.crafting.Crafting;
import com.jamesdpeters.minecraft.chests.database.DBUtil;
import com.jamesdpeters.minecraft.chests.lang.LangFileProperties;
import com.jamesdpeters.minecraft.chests.listeners.HopperListener;
import com.jamesdpeters.minecraft.chests.listeners.InventoryListener;
@ -27,6 +28,7 @@ import com.jamesdpeters.minecraft.chests.serialize.SpigotConfig;
import com.jamesdpeters.minecraft.chests.storage.autocraft.AutoCraftingStorage;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorage;
import com.jamesdpeters.minecraft.chests.versionchecker.UpdateChecker;
import com.jamesdpeters.minecraft.database.hibernate.HibernateUtil;
import fr.minuskube.inv.InventoryManager;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
@ -42,6 +44,8 @@ import org.bukkit.plugin.java.annotation.plugin.Description;
import org.bukkit.plugin.java.annotation.plugin.Plugin;
import org.bukkit.plugin.java.annotation.plugin.author.Author;
import java.util.UUID;
@Plugin(name = "ChestsPlusPlus", version = BuildConstants.VERSION)
@ApiVersion(ApiVersion.Target.v1_14)
@Description(value = "Minecraft Spigot mod that enhances chests and hoppers, with ChestLinks and Hopper filters!")
@ -83,7 +87,6 @@ public class ChestsPlusPlus extends JavaPlugin {
}
@SuppressWarnings("ConstantConditions")
@Override
public void onEnable() {
int pluginId = 7166;
@ -133,6 +136,20 @@ public class ChestsPlusPlus extends JavaPlugin {
// Remove armour stands if disabled
Utils.fixEntities();
DBUtil.init();
var playerDb = DBUtil.PLAYER;
var partyDb = DBUtil.PARTIES;
var test = playerDb.findPlayer(UUID.fromString("e0e93eb6-2ca4-4ac2-803f-684ce0b69b2c"));
getLogger().info("Original parties: "+test.getOwnedParties());
var party = partyDb.findParty(test, "Test Party 2");
party = party == null ? partyDb.createParty(test, "Test Party 2") : party;
getLogger().info("Found party: "+party);
getLogger().info("Players parties: "+test.getOwnedParties());
//Load storages after load.
Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> {
Crafting.load();
@ -153,6 +170,7 @@ public class ChestsPlusPlus extends JavaPlugin {
public void onDisable() {
super.onDisable();
Config.save();
HibernateUtil.close();
// //Remove entities that could have been left behind from bad save files/crashes etc.
// Utils.fixEntities();
}

View File

@ -0,0 +1,27 @@
package com.jamesdpeters.minecraft.chests.database;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.database.dao.PlayerDatabase;
import com.jamesdpeters.minecraft.chests.database.dao.PlayerPartyDatabase;
import com.jamesdpeters.minecraft.chests.database.entities.Player;
import com.jamesdpeters.minecraft.chests.database.entities.PlayerParty;
import com.jamesdpeters.minecraft.database.hibernate.HibernateUtil;
public class DBUtil {
/**
* ALL HIBERNATE ENTITIES
*/
private final static Class<?>[] entities = {
Player.class,
PlayerParty.class
};
public final static PlayerDatabase PLAYER = new PlayerDatabase();
public final static PlayerPartyDatabase PARTIES = new PlayerPartyDatabase();
public static void init() {
HibernateUtil.init(ChestsPlusPlus.PLUGIN.getDataFolder(), entities);
}
}

View File

@ -0,0 +1,22 @@
package com.jamesdpeters.minecraft.chests.database.dao;
import com.jamesdpeters.minecraft.chests.database.entities.Player;
import com.jamesdpeters.minecraft.database.hibernate.Database;
import org.bukkit.OfflinePlayer;
import java.util.UUID;
public class PlayerDatabase extends Database<Player> {
public PlayerDatabase() {
super(Player.class);
}
public Player findPlayer(UUID uuid) {
return findEntity(uuid).orElseGet(() -> new Player(uuid));
}
public Player findPlayer(OfflinePlayer player) {
return findPlayer(player.getUniqueId());
}
}

View File

@ -0,0 +1,36 @@
package com.jamesdpeters.minecraft.chests.database.dao;
import com.jamesdpeters.minecraft.chests.database.DBUtil;
import com.jamesdpeters.minecraft.chests.database.entities.Player;
import com.jamesdpeters.minecraft.chests.database.entities.PlayerParty;
import com.jamesdpeters.minecraft.database.hibernate.Database;
public class PlayerPartyDatabase extends Database<PlayerParty> {
public PlayerPartyDatabase() {
super(PlayerParty.class);
}
public PlayerParty createParty(Player owner, String name) {
PlayerParty playerParty = findParty(owner, name);
if (playerParty != null)
return playerParty;
playerParty = new PlayerParty();
playerParty.setOwner(owner);
playerParty.setName(name);
saveEntity(playerParty);
DBUtil.PLAYER.refresh(owner);
return playerParty;
}
public PlayerParty findParty(Player owner, String name) {
var query = getQuery("from PlayerParty where owner.playerUUID = :ownerId and name = :name");
query.setParameter("ownerId", owner.getPlayerUUID());
query.setParameter("name", name);
return query.getSingleResult();
}
}

View File

@ -0,0 +1,40 @@
package com.jamesdpeters.minecraft.chests.database.entities;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import java.util.List;
import java.util.UUID;
@Entity
@Getter
@ToString
@NoArgsConstructor
public class Player {
public Player(UUID uuid) {
playerUUID = uuid;
}
@Id
private UUID playerUUID;
@OneToMany(mappedBy = "owner")
@ToString.Exclude
private List<PlayerParty> ownedParties;
@ManyToMany(mappedBy = "members")
@ToString.Exclude
private List<PlayerParty> playerParties;
public OfflinePlayer getOfflinePlayer() {
return Bukkit.getOfflinePlayer(playerUUID);
}
}

View File

@ -0,0 +1,43 @@
package com.jamesdpeters.minecraft.chests.database.entities;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.util.List;
@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@Table(uniqueConstraints = {
@UniqueConstraint(columnNames = {"NAME", "OWNER_PLAYERUUID"})
})
public class PlayerParty {
@Id
@GeneratedValue
private Long partyId;
@Column(nullable = false)
private String name;
@JoinColumn(nullable = false)
@ManyToOne(optional = false)
private Player owner;
@ManyToMany
@ToString.Exclude
private List<Player> members;
}

View File

@ -15,6 +15,7 @@
</properties>
<modules>
<module>ChestsPlusPlus-Database</module>
<module>ChestsPlusPlusAPI</module>
<module>ChestsPlusPlus_1_17_R1</module>
<module>ChestsPlusPlus_1_16_R3</module>