https://github.com/elialm7/simple-crud
simple crud library for creating crud classes out of an annotated entity class (NOT AN ORM)
https://github.com/elialm7/simple-crud
crud jdbi3 library mysql postgresql
Last synced: 5 months ago
JSON representation
simple crud library for creating crud classes out of an annotated entity class (NOT AN ORM)
- Host: GitHub
- URL: https://github.com/elialm7/simple-crud
- Owner: elialm7
- Created: 2025-09-21T22:56:28.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-10-01T04:17:10.000Z (9 months ago)
- Last Synced: 2025-10-01T06:21:40.030Z (9 months ago)
- Topics: crud, jdbi3, library, mysql, postgresql
- Language: Java
- Homepage:
- Size: 107 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.MD
Awesome Lists containing this project
README
# Simple - CRUD Library for Java
A lightweight, annotation-driven CRUD library for Java with automatic SQL generation and type transformations. Supports **MySQL and PostgreSQL fully**.
Built on top of JDBI.
## Features
* **Zero configuration**: Define entities with annotations.
* **Automatic SQL generation**: INSERT, UPDATE, SELECT, DELETE statements created automatically.
* **Type transformations**: JSON, arrays, enums, UUIDs, timestamps handled automatically.
* **Dynamic Filtering**: Powerful filtering with operators (LIKE, IN, BETWEEN, IS_NULL, etc.).
* **Batch Operations**: Efficient bulk inserts.
* **Automatic Timestamps**: `@CreatedDate` and `@UpdatedDate` annotations.
* **Default Values**: `@Default` annotation for fallback values.
* **Flexible Mapping**: `getCustomRowMapper()` for mapping to DTOs without `@Table` annotation.
---
## 1. Complete Example
### Entity
```java
@Table(value = "complex_entities", schema = "public", dialect = Dialect.POSTGRESQL)
public class TestUserPostgresql {
@Id(autoGenerated = true)
private Long id;
@Column("entity_name")
private String name;
@UUID(autoGenerate = true)
@Column("uuid_field")
private java.util.UUID uuid;
@UUID(autoGenerate = false)
@Column("manual_uuid")
private String manualUuid;
@JsonColumn
@Column("preferences_json")
private UserPreferences preferences;
@JsonColumn
private Map metadata;
@JsonColumn
@Column("raw_json")
private JsonNode rawJson;
@ArrayColumn(separator = ",")
private List tags;
@ArrayColumn(separator = "|")
private String[] categories;
@EnumColumn(EnumColumn.EnumType.STRING)
private Status status;
@EnumColumn(EnumColumn.EnumType.ORDINAL)
private Priority priority;
@EnumColumn(EnumColumn.EnumType.CODE)
private Department department;
@FileColumn
private byte[] document;
@Default("true")
private Boolean active;
@Default("0")
private Integer attempts;
@CreatedDate
@Column("created_at")
private LocalDateTime createdAt;
@UpdatedDate
@Column("updated_at")
private LocalDateTime updatedAt;
@Ignore
private String temporaryField;
}
```
### Supporting Classes
```java
public class UserPreferences {
private String theme;
private boolean notifications;
private Map settings;
// getters/setters
}
public enum Status { ACTIVE, INACTIVE }
public enum Priority { LOW, MEDIUM, HIGH }
public enum Department {
SALES("SALE"), ENGINEERING("ENG");
private final String code;
Department(String code) { this.code = code; }
public String getCode() { return code; }
}
```
---
### CRUD Class
```java
public class TestUserCRUD extends CRUD {
public TestUserCRUD(Jdbi jdbi) { super(jdbi, TestUserPostgresql.class, Long.class); }
}
```
---
## 2. Example Usage
```java
Jdbi jdbi = Jdbi.create("jdbc:postgresql://localhost/mydb", "user", "pass");
TestUserCRUD crud = new TestUserCRUD(jdbi);
// Crear usuario
TestUserPostgresql user = new TestUserPostgresql();
user.setName("John Doe");
user.setPreferences(new UserPreferences("dark", true, Map.of("lang", "en")));
user.setMetadata(Map.of("version", "1.0"));
user.setTags(List.of("important", "test"));
user.setCategories(new String[]{"cat1", "cat2"});
user.setStatus(Status.ACTIVE);
user.setPriority(Priority.HIGH);
user.setDepartment(Department.ENGINEERING);
user.setActive(true); // Usará el valor por defecto si es null
Long id = crud.save(user);
// Leer todos
List allUsers = crud.findAll();
// Buscar por ID
Optional oneUser = crud.findById(id);
// Filtros dinámicos
Map filters = new HashMap<>();
filters.put("name_LIKE", "John"); // LIKE '%John%'
filters.put("status", "ACTIVE"); // EQUALS
filters.put("priority_GREATER_THAN", 1);
filters.put("tags_LIKE", "%test%"); // Filtra sobre el string unido
filters.put("uuid_IS_NOT_NULL", ""); // Verifica UUID no nulo
List filteredUsers = crud.findAll(filters);
// Filtros avanzados
filters.clear();
filters.put("priority_BETWEEN", "1,3"); // BETWEEN 1 AND 3
filters.put("department_IN", "SALE,ENG"); // IN ('SALE', 'ENG')
filteredUsers = crud.findAll(filters);
// Actualizar
user.setName("John Updated");
crud.update(user);
// Eliminar
crud.deleteById(id);
// Inserción en lote
List users = createManyUsers();
crud.saveAll(users);
```
---
## 3. Database Schema Examples
### PostgreSQL
```sql
CREATE TABLE public.complex_entities (
id BIGSERIAL PRIMARY KEY,
entity_name VARCHAR(255),
uuid_field UUID,
manual_uuid UUID,
preferences_json JSONB,
metadata JSONB,
raw_json JSONB,
tags TEXT,
categories TEXT,
status VARCHAR(50),
priority INTEGER,
department VARCHAR(10),
document BYTEA,
active BOOLEAN DEFAULT TRUE,
attempts INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### MySQL
```sql
CREATE TABLE complex_entities (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
entity_name VARCHAR(255) NULL,
uuid_field VARCHAR(36) NULL,
manual_uuid VARCHAR(36) NULL,
preferences_json JSON NULL,
metadata JSON NULL,
raw_json JSON NULL,
tags TEXT NULL,
categories TEXT NULL,
status VARCHAR(50) NULL,
priority INT NULL,
department VARCHAR(10) NULL,
document LONGBLOB NULL,
active TINYINT(1) DEFAULT 1 NULL,
attempts INT DEFAULT 0 NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP
);
```
---
## 4. Supported Data Types
| Java Type | PostgreSQL | MySQL | Notes |
| ----------------------- | --------------- | --------------- | ------------------------------------- |
| String | VARCHAR/TEXT | VARCHAR/TEXT | Regular string |
| UUID (auto/manual) | UUID | VARCHAR(36) | Native in PG, string in MySQL |
| Object / Map / JsonNode | JSONB | JSON | Auto-serialized via Jackson |
| List | TEXT | TEXT | Comma-separated or custom separator |
| String\[] | TEXT | TEXT | Use @ArrayColumn for custom separator |
| Enum (STRING) | VARCHAR(50) | VARCHAR(50) | Stores enum name |
| Enum (ORDINAL) | INTEGER | INT | Stores enum ordinal (0,1,2…) |
| Enum (CODE) | VARCHAR(10) | VARCHAR(10) | Stores custom code via `getCode()` |
| byte\[] | BYTEA | LONGBLOB | File storage |
| Boolean | BOOLEAN | TINYINT(1) | With `@Default` support |
| Integer | INTEGER | INT | With `@Default` support |
| LocalDateTime | TIMESTAMP | TIMESTAMP | Used for audit fields |
---
# CRUD Library - Data Type Mapping Diagram
| Java Type | Annotation | PostgreSQL Column | MySQL Column | Notes |
| ------------------------------- | ------------------------------- | --------------------- | --------------------- | -------------------------------------------------- |
| `String` | `@Column` | `VARCHAR(n)` / `TEXT` | `VARCHAR(n)` / `TEXT` | Simple string mapping |
| `java.util.UUID` | `@UUID(autoGenerate = true)` | `UUID` | `VARCHAR(36)` | Auto-generated, native in PG |
| `String` (Manual UUID) | `@UUID(autoGenerate = false)` | `UUID` | `VARCHAR(36)` | You provide value, PG casts `::uuid` |
| `Object` / `Map` | `@JsonColumn` | `JSONB` | `JSON` | Auto-serialized via Jackson, PG casts `::jsonb` |
| `JsonNode` | `@JsonColumn` | `JSONB` | `JSON` | Raw JSON, can store any structure |
| `List` | `@ArrayColumn(separator=",")` | `TEXT` | `TEXT` | Stored as comma-separated string |
| `String[]` | `@ArrayColumn(separator=" | ")\` | `TEXT` | `TEXT` | Stored as pipe-separated string |
| Enum (STRING) | `@EnumColumn(EnumType.STRING)` | `VARCHAR(50)` | `VARCHAR(50)` | Stores enum name |
| Enum (ORDINAL) | `@EnumColumn(EnumType.ORDINAL)` | `INTEGER` | `INT` | Stores enum ordinal (0,1,2…) |
| Enum (CODE) | `@EnumColumn(EnumType.CODE)` | `VARCHAR(10)` | `VARCHAR(10)` | Stores custom code via `getCode()` |
| `byte[]` | `@FileColumn` | `BYTEA` | `LONGBLOB` | File storage |
| `Boolean` | `@Default("true")` | `BOOLEAN` | `TINYINT(1)` | Default value support |
| `Integer` | `@Default("0")` | `INTEGER` | `INT` | Default value support |
| `LocalDateTime` | `@CreatedDate` / `@UpdatedDate` | `TIMESTAMP` | `TIMESTAMP` | Auto timestamps for creation/update |
| Any Field | `@Ignore` | N/A | N/A | Field is excluded from all DB operations |
---
## 5. Supported Databases
| Database | Support |
| ---------- | --------------------------------------------------------- |
| PostgreSQL | ✅ **Full support** (UUID, JSONB, arrays, enums, dialect-specific casts) |
| MySQL 5.7+ | ✅ **Full support** (UUID as string, JSON, arrays, enums) |
| Others | ⚠ Untested – basic types might work, but no guarantees. |
> ✅ **Only MySQL and PostgreSQL are officially supported and fully tested.** Other databases may work for basic operations but lack dialect-specific optimizations.
---
## 7. Notes & Best Practices
* **UUID**: For PostgreSQL, prefer `java.util.UUID` type for native handling. For MySQL, `String` is fine.
* **JSON**: Annotate with `@JsonColumn`. Supports complex objects, maps, or `JsonNode`.
* **Arrays**: Annotate with `@ArrayColumn(separator)`. Filtering is done on the *joined string*.
* **Enums**: Use `@EnumColumn` and choose `STRING` (recommended for safety), `ORDINAL` (fragile), or `CODE` (custom).
* **Files**: Use `@FileColumn` with `byte[]`.
* **Timestamps**: Use `@CreatedDate` (set once) and `@UpdatedDate` (set on every update).
* **Defaults**: Use `@Default` to provide fallback values for `null` fields.
* **Ignore**: Use `@Ignore` for fields that should never touch the database.
* **Batch Operations**: Use `saveAll(List)` for high-performance bulk inserts.
* **Transactions**: All write operations (`save`, `update`, `delete`) are automatically wrapped in transactions via JDBI.
---
## 8. Dependencies
To use the CRUD library, you need the following libraries in your project:
### Maven
```xml
org.jdbi
jdbi3-core
3.41.0
org.postgresql
postgresql
42.7.0
mysql
mysql-connector-java
8.1.0
com.fasterxml.jackson.core
jackson-databind
2.17.1
org.slf4j
slf4j-api
2.0.12
```
### Notes
* PostgreSQL and MySQL are the officially tested databases.
* Jackson is **required** for `@JsonColumn` functionality.
* JDBI handles all SQL generation, object mapping, and transactions.
* Other JDBC-compatible databases **might work**, but have not been fully tested and lack dialect-specific features.