{"id":49006143,"url":"https://github.com/ezframework/jaloquent","last_synced_at":"2026-05-22T22:06:55.102Z","repository":{"id":351564542,"uuid":"1211625596","full_name":"EzFramework/Jaloquent","owner":"EzFramework","description":"Eloquent-style model and repository layer built on top of the EzFramework query builder. Provides an active record implementation with support for relationships, eager loading, and more. Inspired by Laravel's Eloquent ORM, but designed to be lightweight and modular use.","archived":false,"fork":false,"pushed_at":"2026-05-09T22:58:39.000Z","size":723,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-10T00:40:48.407Z","etag":null,"topics":["database-management","database-relationships","eager-loading","java","java-21","java-25","java-database-connectivity","java-package","mysql","orm-library","sqlite"],"latest_commit_sha":null,"homepage":"https://ezframework.github.io/Jaloquent/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EzFramework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-15T15:24:13.000Z","updated_at":"2026-05-09T22:57:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/EzFramework/Jaloquent","commit_stats":null,"previous_names":["ezframework/jaloquent"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/EzFramework/Jaloquent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EzFramework%2FJaloquent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EzFramework%2FJaloquent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EzFramework%2FJaloquent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EzFramework%2FJaloquent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EzFramework","download_url":"https://codeload.github.com/EzFramework/Jaloquent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EzFramework%2FJaloquent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33372739,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-22T21:56:13.512Z","status":"ssl_error","status_checked_at":"2026-05-22T21:56:10.769Z","response_time":265,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database-management","database-relationships","eager-loading","java","java-21","java-25","java-database-connectivity","java-package","mysql","orm-library","sqlite"],"created_at":"2026-04-18T20:12:39.123Z","updated_at":"2026-05-22T22:06:55.097Z","avatar_url":"https://github.com/EzFramework.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Jaloquent\n\n[![](https://jitpack.io/v/EzFramework/Jaloquent.svg)](https://jitpack.io/#EzFramework/Jaloquent)\n[![GitHub Packages](https://img.shields.io/badge/GitHub_Packages-1.2.1-blue?logo=github)](https://github.com/EzFramework/Jaloquent/packages)\n![Codecov](https://img.shields.io/codecov/c/github/EzFramework/Jaker)\n\n\nEloquent-style active-record model and repository layer for Java, built on top of the [EzFramework Java Query Builder](https://github.com/EzFramework/JavaQueryBuilder).  \nSupports both SQL (JDBC) and flat-map stores with a consistent API inspired by Laravel's Eloquent ORM.\n\n---\n\n## Requirements\n\n- Java 21+\n- Maven or Gradle\n\n---\n\n## Installation\n\nJaloquent can be easily installed through Jitpack:\nhttps://jitpack.io/#EzFramework/jaloquent\n\n### Maven\n\nAdd the JitPack repository and the dependency to your `pom.xml`:\n\n```xml\n\u003crepositories\u003e\n    \u003crepository\u003e\n        \u003cid\u003ejitpack.io\u003c/id\u003e\n        \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.EzFramework\u003c/groupId\u003e\n    \u003cartifactId\u003ejaloquent\u003c/artifactId\u003e\n    \u003cversion\u003e1.2.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Gradle\n\n```groovy\nrepositories {\n    maven { url 'https://jitpack.io' }\n}\n\ndependencies {\n    implementation 'com.github.EzFramework:jaloquent:1.2.1'\n}\n```\n\n---\n\n## Quick Start\n\n### 1. Define a model\n\n```java\npublic class PlayerData extends Model {\n    public PlayerData(String id) { super(id); }\n\n    public int getCoins() { return getAs(\"coins\", Integer.class, 0); }\n    public void setCoins(int coins) { set(\"coins\", coins); }\n\n    public String getName() { return getAs(\"name\", String.class); }\n    public void setName(String name) { set(\"name\", name); }\n}\n```\n\n### 2. (Optional) Register a SQL table\n\n```java\nTableRegistry.register(\"players\", \"player_data\", Map.of(\n    \"id\",    \"VARCHAR(36) PRIMARY KEY\",\n    \"name\",  \"VARCHAR(64)\",\n    \"coins\", \"INT\"\n));\n```\n\n### 3. Create a repository\n\n```java\n// Flat-map store (e.g. your own DataStore implementation)\nModelRepository\u003cPlayerData\u003e repo = new ModelRepository\u003c\u003e(\n    myDataStore,\n    \"players\",\n    (id, data) -\u003e {\n        PlayerData p = new PlayerData(id);\n        p.fromMap(data);\n        return p;\n    }\n);\n```\n\n### 4. CRUD\n\n```java\n// Create / update\nPlayerData player = new PlayerData(\"uuid-1234\");\nplayer.setName(\"Alice\");\nplayer.setCoins(500);\nplayer.save(repo);\n\n// Read\nOptional\u003cPlayerData\u003e found = repo.find(\"uuid-1234\");\n\n// Delete\nrepo.delete(\"uuid-1234\");\n```\n\n### 5. Query\n\n```java\n// Simple query\nQuery q = Model.queryBuilder()\n    .whereGreaterThan(\"coins\", 100)\n    .orderBy(\"name\", true)\n    .build();\n\nList\u003cPlayerData\u003e richPlayers = repo.query(q);\n```\n\n### 6. Mass-assignment protection\n\n```java\nPlayerData p = new PlayerData(\"1\");\np.setFillable(\"name\", \"coins\");   // only these keys are accepted by fill()\n// OR\np.setGuarded(\"admin_flag\");        // this key is rejected by fill()\n\np.fill(Map.of(\"name\", \"Bob\", \"admin_flag\", true)); // admin_flag silently dropped\n```\n\n---\n\n## Relationships\n\nJaloquent supports Eloquent-style model relationships. Define them as methods on your model class using the protected factory methods inherited from `Model`.\n\n### HasOne\n\nThe related model holds a foreign key pointing to the parent.\n\n```java\npublic class User extends Model {\n    public User(String id) { super(id); }\n\n    // A User has one Phone (phones.user_id = users.id)\n    public HasOne\u003cPhone\u003e phone() {\n        return hasOne(phoneRepo, \"user_id\");\n    }\n}\n\n// Usage\nOptional\u003cPhone\u003e phone = user.phone().get();\n\n// With additional constraints\nOptional\u003cPhone\u003e workPhone = user.phone()\n    .where(\"type\", \"work\")\n    .get();\n\n// Check existence\nboolean hasPhone = user.phone().exists();\n```\n\nUse a custom local key when the anchor is not the model's primary key:\n\n```java\npublic HasOne\u003cPhone\u003e phoneByEmail() {\n    return hasOne(phoneRepo, \"owner_email\", \"email\"); // phones.owner_email = users.email\n}\n```\n\n### HasMany\n\n```java\npublic class User extends Model {\n    public User(String id) { super(id); }\n\n    // A User has many Posts (posts.user_id = users.id)\n    public HasMany\u003cPost\u003e posts() {\n        return hasMany(postRepo, \"user_id\");\n    }\n}\n\n// Usage\nList\u003cPost\u003e posts = user.posts().get();\n\n// With constraints and limit\nList\u003cPost\u003e recent = user.posts()\n    .where(\"status\", \"published\")\n    .orderBy(\"created_at\", false)\n    .limit(10)\n    .get();\n\nlong count = user.posts().count();\n```\n\n### BelongsTo\n\nThe inverse of `hasOne` / `hasMany`. The foreign key lives on the current model.\n\n```java\npublic class Phone extends Model {\n    public Phone(String id) { super(id); }\n\n    // A Phone belongs to a User (phones.user_id → users.id)\n    public BelongsTo\u003cUser\u003e owner() {\n        return belongsTo(userRepo, \"user_id\");\n    }\n}\n\n// Usage\nOptional\u003cUser\u003e owner = phone.owner().get();\nboolean hasOwner = phone.owner().exists();\n```\n\n### BelongsToMany\n\nA many-to-many relationship mediated by a pivot model. Use `PivotModel` (or a custom pivot subclass) for the intermediate table.\n\n```java\npublic class User extends Model {\n    public User(String id) { super(id); }\n\n    // A User belongs to many Roles via user_roles pivot\n    public BelongsToMany\u003cRole, PivotModel\u003e roles() {\n        return belongsToMany(roleRepo, pivotRepo, PivotModel.FACTORY, \"user_id\", \"role_id\");\n    }\n}\n\n// Retrieve\nList\u003cRole\u003e roles = user.roles().get();\n\n// Attach / detach\nuser.roles().attach(\"role-1\");\nuser.roles().detach(\"role-1\");\n\n// Attach with extra pivot attributes\nuser.roles().attach(\"role-1\", Map.of(\"granted_by\", \"admin\"));\n\n// Detach all\nuser.roles().detachAll();\n\n// Sync — attaches missing IDs, detaches IDs not in the list\nuser.roles().sync(List.of(\"role-1\", \"role-3\"));\n\n// Count\nlong roleCount = user.roles().count();\n```\n\n#### Extra pivot attributes\n\nStore additional data on the pivot entry by passing a map to `attach`:\n\n```java\nuser.roles().attach(\"role-editor\", Map.of(\"granted_at\", \"2026-04-15\", \"granted_by\", \"admin-id\"));\n```\n\nRetrieve the pivot entry directly through its repository if you need to read those extra attributes.\n\n### Pivot ID convention\n\nPivot record IDs are generated as `{parentId}_{relatedId}` (e.g. `\"u1_r2\"`). This is the key used for `attach`, `detach`, and repository-level lookups.\n\n---\n\n## Transactions\n\nJaloquent supports atomic multi-step operations through `TransactionalJdbcStore`.\nImplement the interface in your store, then use the try-with-resources handle or\nthe lambda callback:\n\n```java\n// Try-with-resources (auto-rollback on exception)\ntry (Transaction tx = repo.transaction()) {\n    repo.save(orderModel);\n    repo.save(inventoryModel);\n    tx.commit();\n}\n\n// Lambda callback (auto-commit on success, auto-rollback on exception)\nrepo.transaction(() -\u003e {\n    repo.save(orderModel);\n    repo.save(inventoryModel);\n});\n```\n\nSee the [Transactions documentation](https://ezframework.github.io/Jaloquent/transactions)\nfor the full guide.\n\n---\n\n## License\n\nSee [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fezframework%2Fjaloquent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fezframework%2Fjaloquent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fezframework%2Fjaloquent/lists"}