{"id":16380283,"url":"https://github.com/felixklauke/victoria","last_synced_at":"2026-04-26T23:31:44.649Z","repository":{"id":23060592,"uuid":"98043190","full_name":"felixklauke/victoria","owner":"felixklauke","description":"Experimental replacement for couchbase's default entity converter using GSON instead and providing a powerful DAO API. It's full featured providing extended life cycle observing and database backed on disk data structures alongside with extensive entity management via annotations.","archived":false,"fork":false,"pushed_at":"2023-02-13T05:24:49.000Z","size":110,"stargazers_count":3,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T13:31:33.898Z","etag":null,"topics":["annotations","bucket","converter","couchbase","couchbase-cluster","couchbase-enterprise","dao","database","entity","gson","lifecycle","lifecycle-processing","repo","repository","sasuke","sasukekawaii","tls","victoria"],"latest_commit_sha":null,"homepage":"http://felix-klauke.de","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/felixklauke.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":["FelixKlauke"]}},"created_at":"2017-07-22T16:19:28.000Z","updated_at":"2022-07-07T12:24:53.000Z","dependencies_parsed_at":"2024-12-17T16:44:06.714Z","dependency_job_id":"48398c16-e64c-4c7a-a5ac-8b19ecd9de25","html_url":"https://github.com/felixklauke/victoria","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/felixklauke/victoria","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixklauke%2Fvictoria","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixklauke%2Fvictoria/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixklauke%2Fvictoria/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixklauke%2Fvictoria/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/felixklauke","download_url":"https://codeload.github.com/felixklauke/victoria/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixklauke%2Fvictoria/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32317163,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"ssl_error","status_checked_at":"2026-04-26T23:26:25.802Z","response_time":129,"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":["annotations","bucket","converter","couchbase","couchbase-cluster","couchbase-enterprise","dao","database","entity","gson","lifecycle","lifecycle-processing","repo","repository","sasuke","sasukekawaii","tls","victoria"],"created_at":"2024-10-11T03:51:03.367Z","updated_at":"2026-04-26T23:31:44.630Z","avatar_url":"https://github.com/felixklauke.png","language":"Java","funding_links":["https://github.com/sponsors/FelixKlauke"],"categories":[],"sub_categories":[],"readme":"# Victoria\n\nExperimental replacement for couchbase's default entity converter embedded repository implementation using GSON instead\ncouchbase's dumb reflection based property meta data implementation. Furthermore vitoria provides\na highly advanced database access object layer which you can use to simplify couchbase's java driver \nAPI to a human understandable layer with a lot of useful features like:\n- Custom entity conversion\n- Entity Lifecycle processing\n- Managing arbitrary database entities via annotations\n- Conversion interception to monitor entity serialization\n- Proxied instances of javas main default data structures that will synchronize themselves with a document in your database:\n    - Queue\n    - List\n    - Map\n    - (Iterator)\n- Simple analytics to enhance your database analysis\n- DAOs with a bunch of features to manage your data fast and easy\n\n# Basic Usage\n\n### Plain old repository\n```java\nVictoria victoria = VictoriaFactory.createVictoria();\n        \n// Create a repository by a couchbase bucket\nvictoria.createRepository(bucket);\n        \n// You want to use your own gson instance?\nvictoria.createRepository(bucket, gson);\n        \n// Intercept entity conversion\nvictoria.createRepository(bucket, gson, conversionInterceptor);\n```\n\n### DAO\n```java\nVictoria victoria = VictoriaFactory.createVictoria();\n        \n// Create a basic dao\nvictoria.createDAO(elementClazz, bucket);\n        \n// Create a basic dao but provide the bucket via cluster and entity annotation\nvictoria.createDAO(elementClazz, couchbaseCluster);\n        \n// Create a basic dao but provide your own gson instance\nvictoria.createDAO(elementClazz, bucket, gson);\n        \n// Create a basic dao and intercept entity conversion\nvictoria.createDAO(elementClazz, bucket, gson, conversionInterceptor);\n```\n\n# Annotations for DAO Entities\n\n### EntityBucket\n```java \n@EntityBucket( \"bucketName\" ) \npublic class PlayerModel {\n```\n\nYou can provide the bucket of an entity via the `@EntityBucket` annotation.\n\n### EntityType\n```java \n@EntityType( \"player\" ) \npublic class PlayerModel {\n```\n\nWhen you work with an indexed bucket you should ensure youre using an index on the `type` field. \nThe given type will be serialized in the JSON Version of your entity but won't be visible in your entity.\n\n### EntityId\n```java \n@EntityId( prefix = \"player::\" )\nprivate final UUID uniqueId;\n```\n\nOne field of your entity should provide the id of the future document in the database. It is recommended\nthat you prepend a prefix to mark the source application of your entity.\n\n### EntityTTL\n```java \n@EntityTTL( 20 )\npublic class PlayerModel {\n```\n\nYou can give your database document a time to live in seconds via this annotation. Remember that this\nwill take the ttl in seconds when your TTL is under 30 days. You will have to use an unix timestamp if\nyour ttl should be higher than 30 days. \n\n### EntityWatcher\n```java \n@EntityWatcher( BankAccountWatcher.class )\npublic class BankAccount {\n```\n\nYou can provide the class of a lifecycle watcher. Take a look at lifecycle processing.\n\n# Example Entity\n```java\n@EntityTTL(20)\n@EntityBucket(\"high\")\n@EntityType(\"testModel\")\n@EntityWatcher(TestModelWatcher.class)\npublic class TestModel {\n\n    @EntityId(prefix = \"test:\")\n    private final UUID uniqueId;\n    private final Map\u003cString, String\u003e metaDataContainer;\n\n    public TestModel(UUID uniqueId, Map\u003cString, String\u003e metaDataContainer) {\n        this.uniqueId = uniqueId;\n        this.metaDataContainer = metaDataContainer;\n    }\n\n    public UUID getUniqueId() {\n        return uniqueId;\n    }\n\n    public Map\u003cString, String\u003e getMetaDataContainer() {\n        return metaDataContainer;\n    }\n\n    @Override\n    public String toString() {\n        return \"TestModel{\" +\n                \"uniqueId=\" + uniqueId +\n                \", metaDataContainer=\" + metaDataContainer +\n                '}';\n    }\n}\n```\n\n# Lifecycle processing\nYou can implement the LifecycleWatcher\u003cElementType\u003e to watch your entities lifecycle. Remember there\nare two ways and entity can be loaded: Via ID earch or via N1ql. Take care of handle both. \n```java\npublic interface LifecycleWatcher\u003cElementType\u003e {\n\n    /**\n     * Called before the entityDocument will be persisted in a bucket.\n     */\n    void prePersist(ElementType element, EntityDocument\u003cElementType\u003e entityDocument);\n\n    /**\n     * Called after an element was loaded by its primary ID.\n     */\n    void postLoad(ElementType element, EntityDocument\u003cElementType\u003e entityDocument);\n\n    /**\n     * Called after an element was loaded with a n1ql query.\n     */\n    void postLoad(ElementType element, N1qlQueryRow row);\n\n    /**\n     * Called after an entity was persisted in a bucket.\n     */\n    void postPersist(ElementType element, EntityDocument\u003cElementType\u003e entityDocument);\n}\n```\n\n# Conversion Interception\nIf you want to change the behavior of the EntityConverter without writing your own\nconverter use a conversion interceptor that will be called whenever an entity is \nserialized or deserialized: \n```java\npublic interface ConversionInterceptor {\n\n    void onEntityDeserialization(EntityDocument\u003cObject\u003e entityDocument);\n\n    void onEntitySerialization(JsonDocument jsonDocument, Class entityClass);\n}\n```\n\n# Proxied Datastructures\nYou want to manage your data in a java data structure like a list or a queue but you dont want\nto handle the persistence of the data on your own? Use proxies: \n\n### List\n```java\nList\u003cModel\u003e list = ProxiedDatastructures.createList(databaseDocumentName, bucket);\n```\n\n### Map\nSadly we can only support Maps with a String as key because couchbase sucks.\n```java\nMap\u003cString, Model\u003e map = ProxiedDatastructures.createMap(databaseDocumentName, bucket);\n```\n\n### Queue\n```java\nQueue\u003cTestModel\u003e queue = ProxiedDatastructures.createQueue(databaseDocumentName, bucket);\n```\n\nCAUTION: We currently dont hold a lock on proxied documents in a database, so dont modify a document from other sources.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixklauke%2Fvictoria","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffelixklauke%2Fvictoria","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixklauke%2Fvictoria/lists"}