Thanks to visit codestin.com
Credit goes to github.com

Skip to content

caoli5288/SimpleORM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SimpleORM

A Bukkit plugin provides a central ORM Manager. It have no reload issue from Bukkit's build-in ORM support.

Features

  • Centralized ORM: Manage your database connections through a central plugin, avoiding reload issues.
  • Ebean Integration: Leverages the powerful Ebean ORM for easy database operations.
  • Virtual Thread Support: Optionally use Java 21+ virtual threads for highly efficient I/O-bound tasks.
  • Redis Integration: Includes a Redis wrapper for distributed caching and messaging.
  • Serialization: Provides a simple serializer based on Gson with Bukkit objects and JSR310 support.
  • Distributed L2 Cache: Implements a distributed cache layer on top of Redis.

Usage

  1. Put the SimpleORM plugin jar into your server's /plugins folder.
  2. Start your server. A configuration folder /plugins/SimpleORM will be created.
  3. Configure your database in the config.yml file.
  4. SimpleORM will be available as a service for other plugins to use.

For a sample implementation, see the xKit project.

Basic Database Setup

If you want to use this library in your own plugin. code your main class like this. See Ebean ORM

public class MyPlugin extends JavaPlugin {
    
    @Override
    public void onEnable() {
        /*
         * If you dont whan to use manager object, follow this
         * code. NOT RECOMMEND.
         *
         * EbeanHandler handler = new EbeanHandler();
         * handler.setDriver("com.mysql.jdbc.Driver");
         * handler.setUrl("jdbc:mysql://localhost:3306/database");
         * handler.setUserName("userName");
         * handler.setPassword("password");
         *
         * Use manager object will gen and read config field automatic.
         * and will store handler into a map, your can get it even
         * your plugin reload.
         *
         */
        // EbeanManager manager = EbeanManager.DEFAULT;
        EbeanManager manager = getServer().getServicesManager()
                .getRegistration(EbeanManager.class)
                .getProvider();
        EbeanHandler handler = manager.getHandler(this);

        if (!handler.isInitialize()) {
            handler.define(MyClass.class);
            handler.define(MyOther.class);
            try {
                handler.initialize();
            } catch(Exception e) {
                // Do what you want to do.
            }
        }
        // This function will inject into Bukkit's build-in 
        // ORM support.
        handler.reflect();
        // This function will try to create not exists tables.
        handler.install();
        // Injected build-in method. Return initialized 
        // Ebean server.
        EbeanServer server = this.getDatabase();
        // EbeanServer server = handler.getServer();
        // ...
    }
    
    public void function() {
        MyClass my = getDatabase.find(MyClass.class)
                                .where()
                                .eq("name", "zmy")
                                .findUnique();
        System.out.print(my.getName());
        // ...
    }
}

Code your entity class like this. See More Example.

@Entity
@Table(name = "o_table")
public class MyClass {
    
    @Id
    private int id;
    
    @Column
    private String name;
    
    // Put getter and setter.
}

Configure field will create automatic in your plguin's default config file. Like this.

dataSource:
  driver: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost/database
  userName: username
  password: password

Attention

  • A @ManyToOne field is lazy load!
  • A @ManyToOne field is not support on sqlite platform!

Redis wrapper

import com.mengcraft.simpleorm.ORM
import com.mengcraft.simpleorm.RedisWrapper

RedisWrapper redisWrapper = ORM.globalRedisWrapper();
redisWrapper.open(redis -> {
    redis.set("my_key", "my_value");
    // more codes here
});

redisWrapper.subscribe("my_channel", message -> {
    Foo foo = Foo.decode(message);
    // codes here
});

redisWrapper.publish("my_channel", "my_message");

If you want to enable sentinel mode, make sure master_name is a non-empty string, or make sure it is null. An example is shown below.

redis:
  master_name: i_am_master
  url: redis://host1:26379,host2:26379,host3:26379
  max_conn: 20

Serializer

Simple serializer and deserializer based on Gson with ConfigurationSerializable, ScriptObjectMirror and JSR310 supported.

import com.google.common.base.Preconditions
import com.mengcraft.simpleorm.ORM
import org.bukkit.Bukkit
import org.bukkit.Location

Location loc = new Location(Bukkit.getWorld("world"), 0, 0, 0)

Map<String, Object> map = ORM.serialize(loc)
Location loc2 = ORM.deserialize(Location.class, map)

Preconditions.checkState(Objects.equals(loc, loc2))

Async executors

Schedule async task to specific async pool or primary thread.

import com.mengcraft.simpleorm.ORM;

import java.util.function.Supplier;

ORM.enqueue("pool_name", () -> "any_async_task")
        .thenComposeAsync(obj -> {
            // Codes here
        })

ORM.sync(() -> "any_sync_task")
        .thenAccept(s -> {
            // Codes here
        })

Distributed L2 caches

import com.mengcraft.simpleorm.ORM
import com.mengcraft.simpleorm.redis.SimpleCache

def static customCalculator(String key) {
    "hello, " + key
}

def cache = ORM.globalRedisWrapper().openCache(SimpleCache.Options.builder()
        .name("sample")
        .calculator(this::customCalculator)
        .clustered(true)
        .expire(300)
        .expire2(3600)
        .build())

cache.get("key")
        .thenAccept({
            cache.set("key", it)
        })

cache.expire("key")

if (cache.isCached("key2")) {
    cache.expire2("key2")
}

About

A Bukkit plugin provides a central ORM Manager.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages