first commit
This commit is contained in:
33
docs/api-query.md
Normal file
33
docs/api-query.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Query API
|
||||
|
||||
Raw SQL is available via `api.query()` with parameter binding.
|
||||
|
||||
## Execute
|
||||
|
||||
```java
|
||||
int rows = api.query().execute(
|
||||
"UPDATE players SET level = level + 1 WHERE id = ?",
|
||||
java.util.Collections.singletonList(1)
|
||||
);
|
||||
```
|
||||
|
||||
## Query
|
||||
|
||||
```java
|
||||
List<String> names = api.query().query(
|
||||
"SELECT name FROM players WHERE level >= ?",
|
||||
java.util.Collections.singletonList(10),
|
||||
rs -> rs.getString("name")
|
||||
);
|
||||
```
|
||||
|
||||
## Transactions
|
||||
|
||||
```java
|
||||
try (Transaction tx = api.beginTransaction()) {
|
||||
tx.execute("UPDATE players SET level = level + 1 WHERE id = ?", java.util.Collections.singletonList(1));
|
||||
tx.commit();
|
||||
} catch (Exception ex) {
|
||||
// rollback on error if needed
|
||||
}
|
||||
```
|
||||
35
docs/api-schema.md
Normal file
35
docs/api-schema.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Schema API
|
||||
|
||||
Schema helpers let you create and update tables programmatically.
|
||||
|
||||
## Example: create table
|
||||
|
||||
```java
|
||||
import com.andrewkydev.database.schema.ColumnSpec;
|
||||
import com.andrewkydev.database.schema.IndexSpec;
|
||||
import com.andrewkydev.database.schema.TableSpec;
|
||||
|
||||
TableSpec table = TableSpec.builder("players")
|
||||
.column(ColumnSpec.builder("id", "BIGINT").primaryKey(true).autoIncrement(true).nullable(false).build())
|
||||
.column(ColumnSpec.builder("name", "VARCHAR(32)").nullable(false).build())
|
||||
.index(new IndexSpec("players_name_idx", java.util.Arrays.asList("name"), false))
|
||||
.build();
|
||||
|
||||
api.schema().createTable(table);
|
||||
```
|
||||
|
||||
## API Methods
|
||||
|
||||
```java
|
||||
api.schema().createDatabase("primalix");
|
||||
api.schema().dropDatabase("primalix");
|
||||
api.schema().createTable(spec);
|
||||
api.schema().dropTable("players");
|
||||
api.schema().addColumn("players", ColumnSpec.builder("level", "INT").build());
|
||||
api.schema().updateColumn("players", ColumnSpec.builder("level", "INT").nullable(false).build());
|
||||
api.schema().dropColumn("players", "level");
|
||||
api.schema().addIndex("players", new IndexSpec("players_name_idx", java.util.Arrays.asList("name"), false));
|
||||
api.schema().dropIndex("players", "players_name_idx");
|
||||
```
|
||||
|
||||
All methods also have async variants returning `CompletableFuture`.
|
||||
40
docs/config.md
Normal file
40
docs/config.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Configuration
|
||||
|
||||
The default config file is `config.yml`:
|
||||
|
||||
```yaml
|
||||
driver: "mysql"
|
||||
host: "localhost"
|
||||
port: 3306
|
||||
database: "primalix"
|
||||
username: "root"
|
||||
password: ""
|
||||
adminDatabase: "postgres"
|
||||
autoTransactions: true
|
||||
|
||||
pool:
|
||||
maxPoolSize: 10
|
||||
minIdle: 2
|
||||
connectionTimeoutMs: 30000
|
||||
idleTimeoutMs: 600000
|
||||
maxLifetimeMs: 1800000
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
- `driver`: `mysql` or `postgres`.
|
||||
- `host`: database host.
|
||||
- `port`: database port.
|
||||
- `database`: default database name for the pool.
|
||||
- `username`: login user.
|
||||
- `password`: login password.
|
||||
- `adminDatabase`: PostgreSQL admin database used for create/drop database.
|
||||
- `autoTransactions`: wrap schema operations in a transaction when possible.
|
||||
|
||||
## Pool Options
|
||||
|
||||
- `maxPoolSize`: maximum connections in pool.
|
||||
- `minIdle`: minimum idle connections.
|
||||
- `connectionTimeoutMs`: connection timeout.
|
||||
- `idleTimeoutMs`: idle timeout.
|
||||
- `maxLifetimeMs`: maximum connection lifetime.
|
||||
91
docs/examples.md
Normal file
91
docs/examples.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Feature Examples
|
||||
|
||||
## 1) Auto ID after insert
|
||||
|
||||
```java
|
||||
PlayerModel player = new PlayerModel();
|
||||
player.setName("Steve");
|
||||
api.orm().insert(player);
|
||||
long id = player.getId();
|
||||
```
|
||||
|
||||
## 2) snake_case default
|
||||
|
||||
```java
|
||||
class PlayerStats {
|
||||
private int totalKills;
|
||||
}
|
||||
// table: player_stats, column: total_kills
|
||||
```
|
||||
|
||||
## 3) findOneWhere & deleteWhere
|
||||
|
||||
```java
|
||||
PlayerModel one = api.orm().findOneWhere(
|
||||
PlayerModel.class,
|
||||
"level >= ?",
|
||||
java.util.Collections.singletonList(10)
|
||||
);
|
||||
|
||||
int deleted = api.orm().deleteWhere(
|
||||
PlayerModel.class,
|
||||
"level < ?",
|
||||
java.util.Collections.singletonList(1)
|
||||
);
|
||||
```
|
||||
|
||||
## 4) @DbColumn(length/unique/nullable)
|
||||
|
||||
```java
|
||||
@DbColumn(length = 32, unique = true, nullable = false)
|
||||
private String username;
|
||||
```
|
||||
|
||||
## 5) findWhere with order/limit/offset
|
||||
|
||||
```java
|
||||
List<PlayerModel> page = api.orm().findWhere(
|
||||
PlayerModel.class,
|
||||
"level >= ?",
|
||||
java.util.Collections.singletonList(10),
|
||||
"level DESC",
|
||||
10,
|
||||
0
|
||||
);
|
||||
```
|
||||
|
||||
## 6) Query Builder
|
||||
|
||||
```java
|
||||
List<PlayerModel> top = api.orm().query(PlayerModel.class)
|
||||
.where("level >= ?", 10)
|
||||
.orderBy("level DESC")
|
||||
.limit(10)
|
||||
.list();
|
||||
```
|
||||
|
||||
## 7) Query Builder + Fluent Conditions + Join
|
||||
|
||||
```java
|
||||
import static com.andrewkydev.database.orm.Conditions.*;
|
||||
|
||||
List<PlayerModel> rows = api.orm().query(PlayerModel.class)
|
||||
.select("players.*")
|
||||
.join("LEFT JOIN clans ON clans.id = players.clan_id")
|
||||
.where(eq("players.status", "ACTIVE").and(gt("players.level", 10)))
|
||||
.groupBy("players.id")
|
||||
.having("COUNT(clans.id) > ?", 0)
|
||||
.orderBy("players.level DESC")
|
||||
.limit(10, 0)
|
||||
.list();
|
||||
```
|
||||
|
||||
## 8) Custom types (UUID/JSON)
|
||||
|
||||
```java
|
||||
@DbJson
|
||||
private java.util.Map<String, Object> metadata;
|
||||
|
||||
// UUID is built-in. Custom type example:
|
||||
api.orm().registerAdapter(MyType.class, new TypeAdapter<MyType>() { ... });
|
||||
```
|
||||
43
docs/orm-query.md
Normal file
43
docs/orm-query.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# ORM Query Builder
|
||||
|
||||
Fluent query builder on top of the ORM.
|
||||
|
||||
## Basic
|
||||
|
||||
```java
|
||||
List<PlayerModel> top = api.orm().query(PlayerModel.class)
|
||||
.where("level >= ?", 10)
|
||||
.orderBy("level DESC")
|
||||
.limit(10)
|
||||
.list();
|
||||
```
|
||||
|
||||
## Fluent Conditions
|
||||
|
||||
```java
|
||||
import static com.andrewkydev.database.orm.Conditions.*;
|
||||
|
||||
List<PlayerModel> players = api.orm().query(PlayerModel.class)
|
||||
.where(eq("status", "ACTIVE").and(gt("level", 10)))
|
||||
.orderBy("level DESC")
|
||||
.list();
|
||||
```
|
||||
|
||||
## Joins + Group By + Having
|
||||
|
||||
```java
|
||||
List<PlayerModel> rows = api.orm().query(PlayerModel.class)
|
||||
.select("players.*")
|
||||
.join("LEFT JOIN clans ON clans.id = players.clan_id")
|
||||
.where("players.level >= ?", 10)
|
||||
.groupBy("players.id")
|
||||
.having("COUNT(clans.id) > ?", 0)
|
||||
.orderBy("players.level DESC")
|
||||
.limit(10, 0)
|
||||
.list();
|
||||
```
|
||||
|
||||
## Select Columns
|
||||
|
||||
If you select a subset of columns, only those are mapped.
|
||||
Missing fields keep default values.
|
||||
30
docs/orm-schema.md
Normal file
30
docs/orm-schema.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# ORM Schema Generation
|
||||
|
||||
`OrmSchema` builds a `TableSpec` from annotated entities.
|
||||
|
||||
## Example
|
||||
|
||||
```java
|
||||
import com.andrewkydev.database.orm.OrmSchema;
|
||||
import com.andrewkydev.database.schema.SqlDialect;
|
||||
import com.andrewkydev.database.schema.TableSpec;
|
||||
|
||||
TableSpec spec = OrmSchema.fromEntity(PlayerModel.class, SqlDialect.MYSQL);
|
||||
api.schema().createTable(spec);
|
||||
```
|
||||
|
||||
## Type Mapping
|
||||
|
||||
Default mapping (when `@DbColumn(type = "...")` is not specified):
|
||||
|
||||
- `String` -> `VARCHAR(length)`
|
||||
- `int`/`Integer` -> `INT`
|
||||
- `long`/`Long` -> `BIGINT`
|
||||
- `short`/`Short` -> `SMALLINT`
|
||||
- `boolean`/`Boolean` -> `BOOLEAN` (PostgreSQL) or `TINYINT(1)` (MySQL)
|
||||
- `float`/`Float` -> `FLOAT`
|
||||
- `double`/`Double` -> `DOUBLE`
|
||||
- `UUID` -> `UUID` (PostgreSQL) or `CHAR(36)` (MySQL)
|
||||
- `@DbJson` -> `JSON` (MySQL) or `JSONB` (PostgreSQL)
|
||||
|
||||
`@DbColumn(length, unique, nullable)` is also applied.
|
||||
119
docs/orm.md
Normal file
119
docs/orm.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# ORM
|
||||
|
||||
The ORM is lightweight: it maps fields to columns and does not manage complex
|
||||
relationships. It supports sync and async operations.
|
||||
|
||||
## Annotations
|
||||
|
||||
- `@DbEntity(table = "players")` sets table name. Default: snake_case class name.
|
||||
- `@DbColumn(name = "username")` overrides column name.
|
||||
- `@DbColumn(type = "VARCHAR(32)")` overrides SQL type for schema generation.
|
||||
- `@DbColumn(length = 32, unique = true, nullable = false)` influences schema generation.
|
||||
- `@DbId(autoIncrement = true)` marks the primary key.
|
||||
- `@DbJson` stores the field as JSON.
|
||||
- `@DbTransient` ignores the field.
|
||||
|
||||
## Example entity
|
||||
|
||||
```java
|
||||
@DbEntity(table = "players")
|
||||
public class PlayerModel {
|
||||
@DbId(autoIncrement = true)
|
||||
private long id;
|
||||
|
||||
@DbColumn(name = "username", nullable = false, unique = true, length = 32)
|
||||
private String name;
|
||||
|
||||
@DbColumn
|
||||
private int level;
|
||||
|
||||
@DbJson
|
||||
private java.util.Map<String, Object> metadata;
|
||||
|
||||
@DbTransient
|
||||
private String temp;
|
||||
|
||||
public PlayerModel() {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## CRUD
|
||||
|
||||
```java
|
||||
EntityManager orm = api.orm();
|
||||
|
||||
orm.insert(entity);
|
||||
orm.update(entity);
|
||||
orm.delete(entity);
|
||||
PlayerModel player = orm.findById(PlayerModel.class, 1L);
|
||||
List<PlayerModel> all = orm.findAll(PlayerModel.class);
|
||||
PlayerModel one = orm.findOneWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
|
||||
List<PlayerModel> many = orm.findWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
|
||||
List<PlayerModel> paged = orm.findWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10), "level DESC", 10, 0);
|
||||
long count = orm.count(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
|
||||
boolean exists = orm.exists(PlayerModel.class, "username = ?", java.util.Collections.singletonList("Steve"));
|
||||
int deleted = orm.deleteWhere(PlayerModel.class, "level < ?", java.util.Collections.singletonList(1));
|
||||
```
|
||||
|
||||
## Query Builder
|
||||
|
||||
```java
|
||||
EntityManager orm = api.orm();
|
||||
|
||||
List<PlayerModel> top = orm.query(PlayerModel.class)
|
||||
.where("level >= ?", 10)
|
||||
.orderBy("level DESC")
|
||||
.limit(10)
|
||||
.list();
|
||||
|
||||
boolean exists = orm.query(PlayerModel.class)
|
||||
.where("username = ?", "Steve")
|
||||
.exists();
|
||||
```
|
||||
|
||||
## Fluent Conditions
|
||||
|
||||
```java
|
||||
import static com.andrewkydev.database.orm.Conditions.*;
|
||||
|
||||
List<PlayerModel> players = orm.query(PlayerModel.class)
|
||||
.where(eq("status", "ACTIVE").and(gt("level", 10)))
|
||||
.list();
|
||||
```
|
||||
|
||||
## Joins, Group By, Having
|
||||
|
||||
```java
|
||||
List<PlayerModel> rows = orm.query(PlayerModel.class)
|
||||
.select("players.*")
|
||||
.join("LEFT JOIN clans ON clans.id = players.clan_id")
|
||||
.groupBy("players.id")
|
||||
.having("COUNT(clans.id) > ?", 0)
|
||||
.list();
|
||||
```
|
||||
|
||||
Selecting a subset of columns maps only those fields; missing fields keep default values.
|
||||
|
||||
## Auto ID on insert
|
||||
|
||||
If `@DbId(autoIncrement = true)` is used and the id is empty (0 or null),
|
||||
`insert()` will read generated keys and set the id back on the entity.
|
||||
|
||||
## Custom Type Adapters
|
||||
|
||||
UUID mapping is built-in. For other types:
|
||||
|
||||
```java
|
||||
orm.registerAdapter(SomeType.class, new TypeAdapter<SomeType>() {
|
||||
@Override
|
||||
public Object toDatabase(SomeType value) {
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SomeType fromDatabase(Object value) {
|
||||
return value == null ? null : SomeType.parse(value.toString());
|
||||
}
|
||||
});
|
||||
```
|
||||
40
docs/overview.md
Normal file
40
docs/overview.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Overview
|
||||
|
||||
Database is a Lumi plugin that provides:
|
||||
|
||||
- HikariCP-backed MySQL/PostgreSQL connections.
|
||||
- Schema helpers for creating/updating tables and indexes.
|
||||
- Raw SQL queries with parameter binding.
|
||||
- Lightweight ORM with annotations, fluent query builder, and async support.
|
||||
|
||||
## Install
|
||||
|
||||
1. Build the jar with Gradle.
|
||||
2. Put the jar into your server plugins folder.
|
||||
3. Start the server once to generate `config.yml`.
|
||||
|
||||
## Accessing the API
|
||||
|
||||
```java
|
||||
import com.andrewkydev.database.DatabaseProvider;
|
||||
import com.andrewkydev.database.DatabaseApi;
|
||||
|
||||
DatabaseApi api = DatabaseProvider.get();
|
||||
```
|
||||
|
||||
## Feature Highlights
|
||||
|
||||
### Auto ID on insert
|
||||
|
||||
If an entity uses `@DbId(autoIncrement = true)` and the id value is empty (0 or null),
|
||||
`insert()` will fetch generated keys and assign the id back to the object.
|
||||
|
||||
### Snake case by default
|
||||
|
||||
If `@DbEntity` and `@DbColumn` names are not set, class and field names are converted to
|
||||
snake_case.
|
||||
|
||||
### Query helpers
|
||||
|
||||
`findOneWhere`, `deleteWhere`, and `findWhere` with sorting/limit/offset are available
|
||||
in the ORM.
|
||||
33
docs/ru/api-query.md
Normal file
33
docs/ru/api-query.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Query API (RU)
|
||||
|
||||
Raw SQL через `api.query()` с биндингом параметров.
|
||||
|
||||
## Execute
|
||||
|
||||
```java
|
||||
int rows = api.query().execute(
|
||||
"UPDATE players SET level = level + 1 WHERE id = ?",
|
||||
java.util.Collections.singletonList(1)
|
||||
);
|
||||
```
|
||||
|
||||
## Query
|
||||
|
||||
```java
|
||||
List<String> names = api.query().query(
|
||||
"SELECT name FROM players WHERE level >= ?",
|
||||
java.util.Collections.singletonList(10),
|
||||
rs -> rs.getString("name")
|
||||
);
|
||||
```
|
||||
|
||||
## Транзакции
|
||||
|
||||
```java
|
||||
try (Transaction tx = api.beginTransaction()) {
|
||||
tx.execute("UPDATE players SET level = level + 1 WHERE id = ?", java.util.Collections.singletonList(1));
|
||||
tx.commit();
|
||||
} catch (Exception ex) {
|
||||
// rollback при ошибке
|
||||
}
|
||||
```
|
||||
35
docs/ru/api-schema.md
Normal file
35
docs/ru/api-schema.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Schema API (RU)
|
||||
|
||||
Помощники для создания и обновления таблиц.
|
||||
|
||||
## Пример: create table
|
||||
|
||||
```java
|
||||
import com.andrewkydev.database.schema.ColumnSpec;
|
||||
import com.andrewkydev.database.schema.IndexSpec;
|
||||
import com.andrewkydev.database.schema.TableSpec;
|
||||
|
||||
TableSpec table = TableSpec.builder("players")
|
||||
.column(ColumnSpec.builder("id", "BIGINT").primaryKey(true).autoIncrement(true).nullable(false).build())
|
||||
.column(ColumnSpec.builder("name", "VARCHAR(32)").nullable(false).build())
|
||||
.index(new IndexSpec("players_name_idx", java.util.Arrays.asList("name"), false))
|
||||
.build();
|
||||
|
||||
api.schema().createTable(table);
|
||||
```
|
||||
|
||||
## Методы
|
||||
|
||||
```java
|
||||
api.schema().createDatabase("primalix");
|
||||
api.schema().dropDatabase("primalix");
|
||||
api.schema().createTable(spec);
|
||||
api.schema().dropTable("players");
|
||||
api.schema().addColumn("players", ColumnSpec.builder("level", "INT").build());
|
||||
api.schema().updateColumn("players", ColumnSpec.builder("level", "INT").nullable(false).build());
|
||||
api.schema().dropColumn("players", "level");
|
||||
api.schema().addIndex("players", new IndexSpec("players_name_idx", java.util.Arrays.asList("name"), false));
|
||||
api.schema().dropIndex("players", "players_name_idx");
|
||||
```
|
||||
|
||||
У всех методов есть async версии с `CompletableFuture`.
|
||||
40
docs/ru/config.md
Normal file
40
docs/ru/config.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Конфигурация
|
||||
|
||||
Файл `config.yml`:
|
||||
|
||||
```yaml
|
||||
driver: "mysql"
|
||||
host: "localhost"
|
||||
port: 3306
|
||||
database: "primalix"
|
||||
username: "root"
|
||||
password: ""
|
||||
adminDatabase: "postgres"
|
||||
autoTransactions: true
|
||||
|
||||
pool:
|
||||
maxPoolSize: 10
|
||||
minIdle: 2
|
||||
connectionTimeoutMs: 30000
|
||||
idleTimeoutMs: 600000
|
||||
maxLifetimeMs: 1800000
|
||||
```
|
||||
|
||||
## Поля
|
||||
|
||||
- `driver`: `mysql` или `postgres`.
|
||||
- `host`: адрес БД.
|
||||
- `port`: порт БД.
|
||||
- `database`: основная база.
|
||||
- `username`: логин.
|
||||
- `password`: пароль.
|
||||
- `adminDatabase`: PostgreSQL админ‑база для create/drop database.
|
||||
- `autoTransactions`: оборачивать schema операции в транзакцию.
|
||||
|
||||
## Pool
|
||||
|
||||
- `maxPoolSize`: максимум соединений.
|
||||
- `minIdle`: минимум idle.
|
||||
- `connectionTimeoutMs`: таймаут подключения.
|
||||
- `idleTimeoutMs`: таймаут простоя.
|
||||
- `maxLifetimeMs`: максимальная жизнь соединения.
|
||||
43
docs/ru/orm-query.md
Normal file
43
docs/ru/orm-query.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# ORM Query Builder (RU)
|
||||
|
||||
Fluent builder над ORM.
|
||||
|
||||
## База
|
||||
|
||||
```java
|
||||
List<PlayerModel> top = api.orm().query(PlayerModel.class)
|
||||
.where("level >= ?", 10)
|
||||
.orderBy("level DESC")
|
||||
.limit(10)
|
||||
.list();
|
||||
```
|
||||
|
||||
## Fluent Conditions
|
||||
|
||||
```java
|
||||
import static com.andrewkydev.database.orm.Conditions.*;
|
||||
|
||||
List<PlayerModel> players = api.orm().query(PlayerModel.class)
|
||||
.where(eq("status", "ACTIVE").and(gt("level", 10)))
|
||||
.orderBy("level DESC")
|
||||
.list();
|
||||
```
|
||||
|
||||
## Join + Group By + Having
|
||||
|
||||
```java
|
||||
List<PlayerModel> rows = api.orm().query(PlayerModel.class)
|
||||
.select("players.*")
|
||||
.join("LEFT JOIN clans ON clans.id = players.clan_id")
|
||||
.where("players.level >= ?", 10)
|
||||
.groupBy("players.id")
|
||||
.having("COUNT(clans.id) > ?", 0)
|
||||
.orderBy("players.level DESC")
|
||||
.limit(10, 0)
|
||||
.list();
|
||||
```
|
||||
|
||||
## Select Columns
|
||||
|
||||
Если выбираете часть колонок, маппятся только они.
|
||||
Остальные поля остаются дефолтными.
|
||||
30
docs/ru/orm-schema.md
Normal file
30
docs/ru/orm-schema.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# ORM Schema (RU)
|
||||
|
||||
`OrmSchema` строит `TableSpec` на основе аннотаций.
|
||||
|
||||
## Пример
|
||||
|
||||
```java
|
||||
import com.andrewkydev.database.orm.OrmSchema;
|
||||
import com.andrewkydev.database.schema.SqlDialect;
|
||||
import com.andrewkydev.database.schema.TableSpec;
|
||||
|
||||
TableSpec spec = OrmSchema.fromEntity(PlayerModel.class, SqlDialect.MYSQL);
|
||||
api.schema().createTable(spec);
|
||||
```
|
||||
|
||||
## Маппинг типов
|
||||
|
||||
По умолчанию:
|
||||
|
||||
- `String` -> `VARCHAR(length)`
|
||||
- `int`/`Integer` -> `INT`
|
||||
- `long`/`Long` -> `BIGINT`
|
||||
- `short`/`Short` -> `SMALLINT`
|
||||
- `boolean`/`Boolean` -> `BOOLEAN` (PostgreSQL) или `TINYINT(1)` (MySQL)
|
||||
- `float`/`Float` -> `FLOAT`
|
||||
- `double`/`Double` -> `DOUBLE`
|
||||
- `UUID` -> `UUID` (PostgreSQL) или `CHAR(36)` (MySQL)
|
||||
- `@DbJson` -> `JSON` (MySQL) или `JSONB` (PostgreSQL)
|
||||
|
||||
`@DbColumn(length, unique, nullable)` применяется автоматически.
|
||||
119
docs/ru/orm.md
Normal file
119
docs/ru/orm.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# ORM (RU)
|
||||
|
||||
Легковесный ORM: поля мапятся в колонки, без сложных связей.
|
||||
Есть sync и async версии.
|
||||
|
||||
## Аннотации
|
||||
|
||||
- `@DbEntity(table = "players")` - имя таблицы. По умолчанию snake_case.
|
||||
- `@DbColumn(name = "username")` - имя колонки.
|
||||
- `@DbColumn(type = "VARCHAR(32)")` - SQL тип для генерации схемы.
|
||||
- `@DbColumn(length = 32, unique = true, nullable = false)` - влияет на schema генерацию.
|
||||
- `@DbId(autoIncrement = true)` - primary key.
|
||||
- `@DbJson` - JSON поле.
|
||||
- `@DbTransient` - игнорировать поле.
|
||||
|
||||
## Пример сущности
|
||||
|
||||
```java
|
||||
@DbEntity(table = "players")
|
||||
public class PlayerModel {
|
||||
@DbId(autoIncrement = true)
|
||||
private long id;
|
||||
|
||||
@DbColumn(name = "username", nullable = false, unique = true, length = 32)
|
||||
private String name;
|
||||
|
||||
@DbColumn
|
||||
private int level;
|
||||
|
||||
@DbJson
|
||||
private java.util.Map<String, Object> metadata;
|
||||
|
||||
@DbTransient
|
||||
private String temp;
|
||||
|
||||
public PlayerModel() {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## CRUD
|
||||
|
||||
```java
|
||||
EntityManager orm = api.orm();
|
||||
|
||||
orm.insert(entity);
|
||||
orm.update(entity);
|
||||
orm.delete(entity);
|
||||
PlayerModel player = orm.findById(PlayerModel.class, 1L);
|
||||
List<PlayerModel> all = orm.findAll(PlayerModel.class);
|
||||
PlayerModel one = orm.findOneWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
|
||||
List<PlayerModel> many = orm.findWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
|
||||
List<PlayerModel> paged = orm.findWhere(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10), "level DESC", 10, 0);
|
||||
long count = orm.count(PlayerModel.class, "level >= ?", java.util.Collections.singletonList(10));
|
||||
boolean exists = orm.exists(PlayerModel.class, "username = ?", java.util.Collections.singletonList("Steve"));
|
||||
int deleted = orm.deleteWhere(PlayerModel.class, "level < ?", java.util.Collections.singletonList(1));
|
||||
```
|
||||
|
||||
## Query Builder
|
||||
|
||||
```java
|
||||
EntityManager orm = api.orm();
|
||||
|
||||
List<PlayerModel> top = orm.query(PlayerModel.class)
|
||||
.where("level >= ?", 10)
|
||||
.orderBy("level DESC")
|
||||
.limit(10)
|
||||
.list();
|
||||
|
||||
boolean exists = orm.query(PlayerModel.class)
|
||||
.where("username = ?", "Steve")
|
||||
.exists();
|
||||
```
|
||||
|
||||
## Fluent Conditions
|
||||
|
||||
```java
|
||||
import static com.andrewkydev.database.orm.Conditions.*;
|
||||
|
||||
List<PlayerModel> players = orm.query(PlayerModel.class)
|
||||
.where(eq("status", "ACTIVE").and(gt("level", 10)))
|
||||
.list();
|
||||
```
|
||||
|
||||
## Join, Group By, Having
|
||||
|
||||
```java
|
||||
List<PlayerModel> rows = orm.query(PlayerModel.class)
|
||||
.select("players.*")
|
||||
.join("LEFT JOIN clans ON clans.id = players.clan_id")
|
||||
.groupBy("players.id")
|
||||
.having("COUNT(clans.id) > ?", 0)
|
||||
.list();
|
||||
```
|
||||
|
||||
Если выбрать часть колонок, маппятся только они, остальные остаются дефолтными.
|
||||
|
||||
## Auto ID
|
||||
|
||||
Если `@DbId(autoIncrement = true)` и id пустой (0/null),
|
||||
`insert()` получает generated keys и прописывает id в объект.
|
||||
|
||||
## Type Adapters
|
||||
|
||||
UUID уже поддержан. Для других типов:
|
||||
|
||||
```java
|
||||
orm.registerAdapter(SomeType.class, new TypeAdapter<SomeType>() {
|
||||
@Override
|
||||
public Object toDatabase(SomeType value) {
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SomeType fromDatabase(Object value) {
|
||||
return value == null ? null : SomeType.parse(value.toString());
|
||||
}
|
||||
});
|
||||
```
|
||||
34
docs/ru/overview.md
Normal file
34
docs/ru/overview.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Overview (RU)
|
||||
|
||||
Database - SQL plugin for Lumi with MySQL/PostgreSQL, HikariCP pooling,
|
||||
schema helpers, raw SQL, and a lightweight ORM with fluent query builder.
|
||||
|
||||
## Установка
|
||||
|
||||
1. Соберите jar через Gradle.
|
||||
2. Поместите jar в папку plugins сервера.
|
||||
3. Запустите сервер один раз для генерации `config.yml`.
|
||||
|
||||
## Доступ к API
|
||||
|
||||
```java
|
||||
import com.andrewkydev.database.DatabaseProvider;
|
||||
import com.andrewkydev.database.DatabaseApi;
|
||||
|
||||
DatabaseApi api = DatabaseProvider.get();
|
||||
```
|
||||
|
||||
## Основные возможности
|
||||
|
||||
### Auto ID после insert
|
||||
|
||||
Если у поля есть `@DbId(autoIncrement = true)` и id пустой (0 или null),
|
||||
`insert()` получает generated keys и прописывает id в объект.
|
||||
|
||||
### Snake case по умолчанию
|
||||
|
||||
Если не задано `@DbEntity`/`@DbColumn`, имена берутся в snake_case.
|
||||
|
||||
### Удобные ORM методы
|
||||
|
||||
Доступны `findOneWhere`, `deleteWhere` и `findWhere` с сортировкой/лимитом/offset.
|
||||
Reference in New Issue
Block a user