{"id":3587,"url":"https://github.com/dkharrat/NexusData","last_synced_at":"2025-08-03T20:32:49.705Z","repository":{"id":15808639,"uuid":"18548196","full_name":"dkharrat/NexusData","owner":"dkharrat","description":"Core Data for Android","archived":false,"fork":false,"pushed_at":"2018-05-28T08:03:21.000Z","size":8392,"stargazers_count":72,"open_issues_count":8,"forks_count":19,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-08-16T14:34:48.230Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dkharrat.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-04-08T06:48:14.000Z","updated_at":"2024-02-01T08:07:31.000Z","dependencies_parsed_at":"2022-09-24T04:43:25.450Z","dependency_job_id":null,"html_url":"https://github.com/dkharrat/NexusData","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkharrat%2FNexusData","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkharrat%2FNexusData/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkharrat%2FNexusData/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkharrat%2FNexusData/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dkharrat","download_url":"https://codeload.github.com/dkharrat/NexusData/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228567009,"owners_count":17937983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-01-05T20:16:45.698Z","updated_at":"2024-12-07T05:30:43.211Z","avatar_url":"https://github.com/dkharrat.png","language":"Java","funding_links":[],"categories":["Libraries","库"],"sub_categories":["Database","[](https://github.com/JStumpp/awesome-android/blob/master/readme.md#orm)ORM"],"readme":"NexusData\n=========\n**Core Data for Android**\n\nNexusData is an object graph and persistence framework for Android. It allows for organizing and managing relational\ndata and serializing it to SQLite or custom stores. The data can be accessed or modified using higher level objects\nrepresenting entities and their relationships. NexusData manages all the objects in the persistence store, tracks\nchanges, and maintains consistency in relationships.\n\nEssentially, it brings Core Data functionality from iOS to Android. However, the library is not intended to be a\nstraight port of Core Data. Instead, it aims to leverage Core Data's concepts, while having the flexibility to evolve\nindependently.\n\nNexusData is not an ORM in that it's more higher-level and is not tied to a specific storage engine. The query interface\nis oblivious to the underlying persistence store.\n\nNexusData supports Android API 10+. This library follows [semantic versioning](http://semver.org/). Note that this\nlibrary is still active in development, and is missing a lot of features. New releases might introduce\ninterface-breaking changes, which will be indicated in the changelog. NexusData 1.0.0 will be the first stable release.\n\nSamples\n-------\n\nFor sample projects that use NexusData, browse the [samples](http://github.com/dkharrat/NexusData/tree/master/samples)\ndirectory.\n\nFeatures\n--------\n* Change tracking and management of objects.\n* Relationship maintenance by automatically propagating related changes to maintain consistency.\n* Support for one-to-one and one-to-many relationships.\n* Lazy loading of the object graph to reduce memory overhead.\n* Flexible query interface that is independent of the underlying storage engine.\n* Model generator that generates java classes from the model.\n* Entity inheritence.\n* Support for atomic and incremental persistence stores.\n* Extensible to different persistence storage. Currently, two storage engines are provided out of the box:\n  * In-memory\n  * SQLite\n* Built-in support for basic attribute types:\n  * Short / Integer / Long\n  * Boolean\n  * Float / Double\n  * String\n  * Enum\n  * Date\n\nLimitations\n-----------\nThe framework is constantly being improved and new features are being implemented. Since it's very early stage, it\ncurrently has some limitations:\n\n* Undo/Redo is not supported.\n* Many-to-many relationships are not supported yet.\n* Schema migrations are not supported yet.\n* Query syntax is currently limited to comparisons and boolean logic. Operations like aggregations and joining are not\n  supported yet.\n* Framework is not yet optimized for large data sets in terms of performance and memory. This is due to the early\n  development of the project and will be improved over time.\n* Custom data types are not supported yet.\n\nApps Using NexusData\n--------------------\nDo you have an app that's utilizing NexusData? [Let me know](mailto:dkharrat@gmail.com) and I'll add a link to it here!\n\nHow to Add NexusData to Your Project\n------------------------------------\nThere are multiple ways to include your project, depending on your build environment:\n\n#### Gradle\n\nAdd the following dependency to your build.gradle file for your project:\n\n    dependencies {\n      compile 'com.github.dkharrat.nexusdata:nexusdata:0.2.1'\n    }\n\n#### Maven\n\nAdd the following dependency to your pom.xml file for your project:\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.github.dkharrat.nexusdata\u003c/groupId\u003e\n        \u003cartifactId\u003enexusdata\u003c/artifactId\u003e\n        \u003cversion\u003e0.2.1\u003c/version\u003e\n        \u003ctype\u003ejar\u003c/type\u003e\n    \u003c/dependency\u003e\n\n#### Android Studio or IntelliJ 13+\n\nAdd the appropriate dependency in your build.gradle file and refresh your project.\n\n#### Eclipse\n\nTBD\n\nHow to Get Started\n--------------------\nFor a complete example of how NexusData can be used, please browse through\n[the samples](https://github.com/dkharrat/NexusData/tree/master/samples) included with the project.\n\n### Defining the model\nThe model is used to provide NexusData with information about the entities and their properties. A model can be defined\neither programmatically or via JSON file. Here's an example of a JSON-based model file for a ToDo app:\n\ntodo.model.json:\n```json\n{\n  \"metaVersion\": 1,\n  \"model\": {\n    \"name\": \"Todo\",\n    \"version\": 3,\n    \"packageName\": \"org.example.todo\",\n    \"entities\": [{\n      \"name\": \"Task\",\n      \"enums\": [{\n        \"name\": \"Priority\",\n        \"values\": [\"HIGH\", \"MEDIUM\", \"LOW\"]\n      }],\n      \"attributes\": [{\n        \"name\": \"title\",\n        \"type\": \"String\"\n      }, {\n        \"name\": \"notes\",\n        \"type\": \"String\"\n      }, {\n        \"name\": \"dueBy\",\n        \"type\": \"Date\"\n      }, {\n         \"name\": \"completed\",\n         \"type\": \"Bool\",\n         \"required\": true,\n         \"default\": false\n       }, {\n         \"name\": \"priority\",\n         \"type\": \"Priority\"\n       }],\n      \"relationships\": [{\n        \"name\": \"assignedTo\",\n        \"destinationEntity\": \"User\",\n        \"inverseName\": \"tasks\",\n        \"toMany\": false\n      }]\n    }, {\n      \"name\": \"User\",\n      \"attributes\": [{\n        \"name\": \"name\",\n        \"type\": \"String\"\n      }],\n      \"relationships\": [{\n        \"name\": \"tasks\",\n        \"destinationEntity\": \"Task\",\n        \"inverseName\": \"assignedTo\",\n        \"toMany\": true\n      }]\n    }]\n  }\n}\n```\n\nThis model (named \"Todo\") defines two entities: `Task` and `User`. A `Task` belongs to a `User`, and a `User` has many\n`Task`s. Also, each entity has some attributes.\n\n### Generating classes from a model file\nNexusData comes with a Model Generator that allows you to generate an appropriate class for each entity. Though using\nthe generator is not necessary to use NexusData, the Model Generator reduces the need to write a lot of repetitive and\nboilerplate code for each entity (getter, setters, etc.). If you choose not to use the Model Generator, you may either\ncreate the classes yourself or use `ManagedObject` directly.\n\nThe model generator source code is located under the `modelgen` directory. To generate the appropriate classes from\nthe above model file, run this command:\n\n    gradle :modelgen:run -Pargs=\"-f /path/to/model/todo.model.json -O /path/to/output/src/main/java\"\n\nThis will parse the `todo.model.json` file and generate the corresponding classes in the\n`src/main/java/org/example/todo` directory. The output of the generator will look something like this:\n\n    03:43:41.970 [main] INFO  c.g.d.n.modelgen.ModelGenerator - Setting up model generator\n    03:43:42.028 [main] INFO  c.g.d.n.modelgen.ModelGenerator - Parsing model file 'todo.model.json'\n    03:43:42.098 [main] INFO  c.g.d.n.modelgen.ModelGenerator - Generating class files for 'Todo' model (version 1)\n    03:43:42.152 [main] INFO  c.g.d.n.modelgen.ModelGenerator - Generating class Task.java\n    03:43:42.161 [main] INFO  c.g.d.n.modelgen.ModelGenerator - Generating class _Task.java\n    03:43:42.184 [main] INFO  c.g.d.n.modelgen.ModelGenerator - Generating class User.java\n    03:43:42.184 [main] INFO  c.g.d.n.modelgen.ModelGenerator - Generating class _User.java\n\nFor each entity, two classes will be generated. For example, for the `Task` entity, `Task.java` and `_Task.java` are\ngenerated. The `_Task.java` file contains all the accessors, enums, and relationships based on the model file. The\nother file, `Task.java`, is an empty class that inherits from `_Task`. The `Task` class can be used to define any custom\ncode or derived properties. The reason for creating two classes is to allow you to re-generate the entity classes if\nthe model changes, while maintaining any custom code associated with the entity in a separate file. The generator will\nnot overwrite your custom class (e.g. `Task.java` in this example) if it already exists, but it will overwrite the\nbase class (e.g. `_Task.java`).\n\nHere's how the generated files look like for the `Task` entity:\n\n_Task.java:\n```java\n// THIS IS AN AUTO-GENERATED CLASS FILE. DO NOT EDIT DIRECTLY.\n\npackage org.example.todo;\n\nimport java.util.Date;\nimport com.github.dkharrat.nexusdata.core.ManagedObject;\n\nclass _Task extends ManagedObject {\n\n    public interface Property {\n        String TITLE = \"title\";\n        String NOTES = \"notes\";\n        String DUE_BY = \"dueBy\";\n        String COMPLETED = \"completed\";\n        String PRIORITY = \"priority\";\n        String ASSIGNED_TO = \"assignedTo\";\n    }\n\n    public enum Priority {\n        HIGH,\n        MEDIUM,\n        LOW,\n    }\n\n    public String getTitle() {\n        return (String)getValue(Property.TITLE);\n    }\n\n    public void setTitle(String title) {\n        setValue(Property.TITLE, title);\n    }\n\n    public String getNotes() {\n        return (String)getValue(Property.NOTES);\n    }\n\n    public void setNotes(String notes) {\n        setValue(Property.NOTES, notes);\n    }\n\n    public Date getDueBy() {\n        return (Date)getValue(Property.DUE_BY);\n    }\n\n    public void setDueBy(Date dueBy) {\n        setValue(Property.DUE_BY, dueBy);\n    }\n\n    public boolean isCompleted() {\n        return (Boolean)getValue(Property.COMPLETED);\n    }\n\n    public void setCompleted(boolean completed) {\n        setValue(Property.COMPLETED, completed);\n    }\n\n    public Priority getPriority() {\n        return (Priority)getValue(Property.PRIORITY);\n    }\n\n    public void setPriority(Priority priority) {\n        setValue(Property.PRIORITY, priority);\n    }\n\n\n    public User getAssignedTo() {\n        return (User)getValue(Property.ASSIGNED_TO);\n    }\n\n    public void setAssignedTo(User assignedTo) {\n        setValue(Property.ASSIGNED_TO, assignedTo);\n    }\n}\n```\n\nTask.java:\n```java\npackage org.example.todo;\n\npublic class Task extends _Task {\n    public Task() {\n    }\n}\n```\n\n### Initializing NexusData Stack\n\nTo setup NexusData in your application, you'll need three main parts: `ObjectModel`, `PersistentStoreCoordinator`,\nand a `ObjectContext`. These can typically be initialized once at startup and used throughout the lifetime of the\napplication.\n\n```java\n// create an ObjectModel that describes the meta model\nObjectModel model = new ObjectModel(app.getAssets().open(\"todo.model.json\"));\n\n// create the persistent store coordinator and its associated store\nPersistentStoreCoordinator storeCoordinator = new PersistentStoreCoordinator(model);\nContext ctx = getApplicationContext(); // the Android context\nPersistentStore cacheStore = new AndroidSqlPersistentStore(ctx, ctx.getDatabasePath(\"todo\"));\nstoreCoordinator.addStore(cacheStore);\n\n// create an ObjectContext that will be used to retrieve or save our objects\nObjectContext mainObjectContext = new ObjectContext(storeCoordinator);\n```\n\n### Creating/Updating Objects\n\n```java\nObjectContext objCtx = getMainObjectContext();\nTask task1 = objCtx.newObject(Task.class);\ntask1.setTitle(\"Get groceries\");\n\nTask task2 = objCtx.newObject(Task.class);\ntask2.setTitle(\"File taxes\");\n\nobjCtx.save();\n```\n\n### Deleting Objects\n\n```java\nobjCtx.delete(task1);\nobjCtx.save();\n```\n\n### Querying All Objects of Specific Type\n\n```java\nList\u003cTask\u003e tasks = objCtx.findAll(Task.class)\n```\n\n### Querying Objects Satisfying a Predicate\n\nFor example, to query all Tasks that are complete:\n\n```java\nFetchRequest\u003cTask\u003e fetchRequest = objCtx.newFetchRequestBuilder(Task.class)\n    .predicate(\"completed == true\")\n    .build();\nList\u003cTask\u003e tasks = objCtx.executeFetchOperation(fetchRequest);\n```\n\n### Use `ObjectContext` and `ManagedObject`s in multiple threads\n\nSimilar to Core Data, `ManagedObject` and `ObjectContext` are not thread-safe, and therefore, should not be used in\nother threads. Each thread must use its own instance of `ObjectContext`. To pass objects between multiple threads,\npass the object's `ObjectID` to the other thread, which can then retrieve the object from it's own `ObjectContext`.\n\nTo synchronize multiple `ObjectContext` with any changes, register a listener and then merge the changes when receiving\na notification, as follows:\n\n```java\nObjectContextNotifier.registerListener(new ObjectContextNotifier.DefaultObjectContextListener() {\n    @Override public void onPostSave(ObjectContext context, ChangedObjectsSet changedObjects) {\n        // ensure that the notification we just got is not from our own context, and that it's from a context using a\n        // persistence store that our context is also using.\n        if (context != mainObjectContext \u0026\u0026 context.getPersistentStoreCoordinator() == mainObjectContext.getPersistentStoreCoordinator()) {\n            mainObjectContext.mergeChangesFromSaveNotification(changedObjects);\n        }\n    }\n});\n```\n\nDocumentation\n-------------\nSee the current [Javadoc](http://dkharrat.github.io/NexusData/javadoc/).\n\nContributing\n------------\nContributions via pull requests are welcome! For suggestions, feedback, or feature requests, please submit an issue.\n\nAuthor\n------\nDia Kharrat - dkharrat@gmail.com\u003cbr/\u003e\nTwitter: [http://twitter.com/dkharrat](http://twitter.com/dkharrat)\n\nLicense\n-------\n    Copyright 2014 Dia Kharrat\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkharrat%2FNexusData","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdkharrat%2FNexusData","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkharrat%2FNexusData/lists"}