{"id":17044792,"url":"https://github.com/keredson/dko","last_synced_at":"2025-04-12T15:31:28.484Z","repository":{"id":10360220,"uuid":"12500051","full_name":"keredson/DKO","owner":"keredson","description":"An ORM for people who hate ORMs.","archived":false,"fork":false,"pushed_at":"2017-05-22T00:47:02.000Z","size":24110,"stargazers_count":49,"open_issues_count":8,"forks_count":7,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-26T10:11:19.535Z","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":"jcarapia/neighborPool","license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/keredson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-08-31T03:28:55.000Z","updated_at":"2024-07-14T04:53:45.000Z","dependencies_parsed_at":"2022-09-22T18:52:04.724Z","dependency_job_id":null,"html_url":"https://github.com/keredson/DKO","commit_stats":null,"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2FDKO","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2FDKO/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2FDKO/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keredson%2FDKO/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/keredson","download_url":"https://codeload.github.com/keredson/DKO/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248589498,"owners_count":21129626,"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-10-14T09:35:31.479Z","updated_at":"2025-04-12T15:31:23.462Z","avatar_url":"https://github.com/keredson.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"DKOs - Data Knowledge Objects\n=============================\n(Or Derek's Objects, depending on who you ask...)\n\n*NEW:* Read the [DKO Presentation](dko_presentation.pdf).\n\nIntroduction\n------------\nDKOs are an ORM for people who hate ORMs.\n\nORMs are a pain.  They promise a world of being free from your database where you just work with good ol' Java.\nYour database server doesn't matter.  Your schema doesn't matter.  Tables and relationships can be abstracted away\nand changing them doesn't have to affect your code.  All you have are some object references and you can modify\nthem willy-nilly and it'll all just work.\n\nWell that's just nonsense.  It may work for a 100 entry blog implementation, but you're not going to process\nmillions of new rows daily with it (or at least not without a world of pain getting there).  Your database is a shared\nresource on a different\nmachine, not an in-memory entity.  And ignoring your schema is a great way to accidentally DOS your database with\nmillions of \"`select * from x where id=35476753`\" style queries.\n\nPlus: **SQL is not the devil!**  It's one of computer science's most successful languages!  The devil \nis SQL built by string concatenation.  And string identifiers.  And a lack of typing.  And a lack of streaming.\n\nDKOs addresses all these issues:\n\n - It's fully typed.\n - It's streaming (by default).\n - It embraces SQL (rather than replaces it).\n - It doesn't use string identifiers for tables/columns/etc.\n - It doesn't hide from you the fact that it's hitting a database (or what SQL it's running).\n \nWant to get started right now?  Try the [Quick Start Guide](QUICK_START.md).\n\nCurious about DKOs on Android?  Check out [Hello Android](examples/helloandroid/README.md).\n\nSupported Databases\n-------------------\nDKOs fully support the following database engines:\n\n - [Microsoft SQL Server](http://www.microsoft.com/en-us/sqlserver/default.aspx)\n - [MySQL](http://www.mysql.com/)\n - [PostgreSQL](http://www.postgresql.org/)\n - [Oracle](http://www.oracle.com/)\n - [HSQL](http://hsqldb.org/)\n - [SQLite3](http://www.sqlite.org/)\n\nPlease contact me if your database is not on this list.  It's usually ~2-3 hours work to add support (assuming I\nhave a working instance to test against).\n\n\nThe Nickel Tour\n---------------\nHello world...\n\n```java\nfor (Bug bug : Bug.ALL.limit(100)) {\n  System.out.println(bug.getId() +\" \"+ bug.getTitle());\n}\n```\n\nThe constant `Bug.ALL` is of type `Query\u003cBug\u003e`, as is `Bug.ALL.limit(100)`.  And `Query\u003cBug\u003e` implements `Iterable\u003cBug\u003e`\n(hence it working in a for loop).\n\nThe class `Bug` is generated (please don't freak out) direct from your database schema.  Is generated code \nevil?  Usually yes, but not always.  It's evil if you generate it, modify it and check it into your VCS.  But if it's a \nbuild artifact (like your `.class` files) that is never touched by human hands (or git)... then it's OK.  And that's\nwhat we do here.  (In fact the ONLY way to generate code with DKO is through an Ant task.)\n\nAnother example:\n\n```java\nfor (Bug bug : Bug.ALL.where(Bug.REPORTER.eq(Bug.ASSIGNEE))) {\n  // people work on their own bugs a lot\n}\n```\n\n`Bug.REPORTER` is static constant `Field\u003cInteger\u003e`.  Fields have methods for all normal SQL comparisons.  Here we're\ncomparing it to another field of the same table.\n\nFor simplicity, let's leave out the for loop going forward...\n\n```java\nBug.ALL.where(Bug.CREATE_DATE.between(new Date(2010,06,30), new Date(2013,09,04)));\n```\n\n```java\nBug.ALL.where(\n    Bug.CREATE_DATE.lt(new Date(2013,03,05))\n    .and(Bug.CLOSE_DATE.isNull())\n);\n```\n\nRemember when I said DKOs embrace SQL?\n\nJoins on foreign keys are easy too:\n\n```java\nQuery\u003cBug\u003e q = Bug.ALL\n    .with(Bug.FK_REPORTER_USER)\n    .where(User.NAME.like(\"%Derek%\"));\n// this only runs one query - no O(n) database ops!\nfor (Bug bug : q) {\n    System.out.println(bug.getReporterFK().getName());\n}\n```\n\nBTW, that works both ways:\n\n```java\nQuery\u003cUser\u003e q = User.ALL\n    .with(Bug.FK_REPORTER_USER)\n    .where(Bug.ESTIMATED_TIME.gt(4.5)) // hours\n// only one joined query (streaming over User) happens here\nfor (User user : q) {\n    // no second query here!\n    for (Bug bug : user.getReporterUserSet()) {\n    }\n}\n```\n\nForeign key relationships aren't limited to one join:\n\n```java\n// joins to two tables\nBug.ALL\n    .with(Bug.FK_REPORTER_USER)\n    .with(Bug.FK_PRODUCT);\n```\n\nNor are they limited to one level deep:\n\n```java\nBug bug = Bug.ALL.with(Bug.FK_REPORTER_USER, User.FK_MANAGER).first();\nSystem.out.println(bug.getReporterFK().getManagerFK().getName());\n```\n\nServer-side updates are supported of course:\n\n```java\nlong count = Bug.ALL\n    .where(Bug.LAST_UPDATED.lt(new Date(2010,06,30)))\n    .set(Bug.PRIORITY, 0)\n    .update();\n```\n\nAs are deletes, inserts, etc.  You get the drill.  Virtually all SQL operations you care about are supported.  Here \nare some highlights:\n\n - Transactions\n - SQL Functions\n - Joins (FK based and non-FK based)\n - Inner Queries\n - Temp Tables\n - Aggregation / Counting\n - Sum / Average\n - Order By\n - Distinct\n - Top / Limit\n - Aliases\n\nPlus some nice touches:\n\n - Reads (outside transactions) default to database mirrors (if you have them).\n - Selected columns that go unused are optimized away in future runs.\n - DKOs warn you if you're needlessly killing your database (like when you forget a `.with(FK)`).\n - Lots of helper functions... (Want a `Map\u003cInteger,Bug\u003e` from some field to your object?  Can do!)\n\nAnd DKOs scale very well.  Measured performance is \u003e98% of raw JDBC for the largest SQL Server databases money can \nbuy.  And they're small enough to power Android apps (using SQLite).\n\nPlus, and I can't stress this enough:  The code is **boringly simple**.  Plain objects with plain variables.  No \nbyte-code rewriting.  No twenty-layers-of-reflection\nhell.  No dictionary-backed objects.  When you want to know what's going on you don't need a PhD.  Only a debugger.\n\nTo learn more, see [DKOs - The Book](http://nosco.googlecode.com/hg/doc/dkos-the-book/dkos-the-book.html).\n\n\n\nHistory\n-------\nThe idea of DKO started in 2006 when I first used [Django](https://www.djangoproject.com), \nliked their query API and thought \"jeez I wish\nJava had this\".  (I had spent the previous six years as a corporate Java developer)\nBut I quickly fell in love with Python, so I never pursued it.\nThen in 2010 I was thrown back into the Java world when I started at \nTwo Sigma Investments.  I was appalled by our internal use/abuse of Hibernate\n(horribly inefficient at our scale), so I implemented DKO as an external open-source project to prove out the \nconcept.  It worked, I brought it in, and it has been in widespread internal use since.  It \npowers hundreds of daily \nproduction-critical jobs and processes, the vast majority *not* written by me (and without any sort of internal mandate\nfor its use), and is the preferred go-to API for database access in the office by developers and data analysts alike.\n\nThe original name of DKOs was [Nosco](https://code.google.com/p/nosco) (Latin for \"get to know\", hence \n\"Data Knowledge Objects\"), but someone pointed out that that rhymed with \"bosco\", and I couldn't have that.  :)\n\nNote: *Two Sigma in no way endorses DKOs.  Opinions stated here are mine and mine alone.*\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeredson%2Fdko","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeredson%2Fdko","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeredson%2Fdko/lists"}