{"id":37027026,"url":"https://github.com/mjdbc/mjdbc","last_synced_at":"2026-01-14T03:11:46.542Z","repository":{"id":57721557,"uuid":"42215174","full_name":"mjdbc/mjdbc","owner":"mjdbc","description":"Small and efficient JDBC wrapper","archived":false,"fork":false,"pushed_at":"2019-05-06T18:17:47.000Z","size":241,"stargazers_count":14,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-18T12:14:04.886Z","etag":null,"topics":["database","dbi","dbi-interface","java","jdbc","mapper","sql","sql-queries","sql-statements","transactions"],"latest_commit_sha":null,"homepage":"","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/mjdbc.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":"2015-09-10T01:47:34.000Z","updated_at":"2023-08-31T16:57:29.000Z","dependencies_parsed_at":"2022-09-26T21:41:33.114Z","dependency_job_id":null,"html_url":"https://github.com/mjdbc/mjdbc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mjdbc/mjdbc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjdbc%2Fmjdbc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjdbc%2Fmjdbc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjdbc%2Fmjdbc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjdbc%2Fmjdbc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mjdbc","download_url":"https://codeload.github.com/mjdbc/mjdbc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjdbc%2Fmjdbc/sbom","scorecard":{"id":651429,"data":{"date":"2025-08-11","repo":{"name":"github.com/mjdbc/mjdbc","commit":"512746c2faf866863859d95a55f631d361b396c7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 1/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T13:36:10.001Z","repository_id":57721557,"created_at":"2025-08-21T13:36:10.001Z","updated_at":"2025-08-21T13:36:10.001Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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","dbi","dbi-interface","java","jdbc","mapper","sql","sql-queries","sql-statements","transactions"],"created_at":"2026-01-14T03:11:46.055Z","updated_at":"2026-01-14T03:11:46.525Z","avatar_url":"https://github.com/mjdbc.png","language":"Java","readme":"__mJDBC__  - Small and efficient JDBC wrapper.\n\n* *Small:* no external dependencies. Jar size is  less than 50kb.\n* *Simple:* no special configuration required. Start using it after 1 line of initialization code.\n* *Reliable:* all SQL statements are parsed and validated on application startup.\n* *Flexible:* switch and use native JDBC interface directly when needed.\n* *Fast:* no runtime overhead when compared to JDBC.\n* *Transactional:* wrap any method into transaction. Real connection is opened on first statement execution.\n* *Extensible:* add support for new data types or override the way built-in types are handled.\n* *Measurable:* profile timings for all SQL queries and transactions.\n* *Open source:* fork and change it.\n\n[View detailed documentation](https://mjdbc.github.io)\n\n[![Build Status](https://travis-ci.org/mjdbc/mjdbc.svg?branch=master)](https://travis-ci.org/mjdbc/mjdbc)\n[![Coverage Status](https://coveralls.io/repos/github/mjdbc/mjdbc/badge.svg?branch=master)](https://coveralls.io/github/mjdbc/mjdbc?branch=master)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.mjdbc/mjdbc/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.mjdbc/mjdbc)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\n## Maven\n```xml\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.github.mjdbc\u003c/groupId\u003e\n        \u003cartifactId\u003emjdbc\u003c/artifactId\u003e\n        \u003cversion\u003e1.4.0\u003c/version\u003e\n    \u003c/dependency\u003e\n```\n\n## Building\n\n```bash\nmvn -DskipTests=true clean package install\n```\n\n## Brief API overview\n\n##### Raw SQL queries\n```java\n    java.sql.DataSource ds = ...; // have a DataSource first. \n    Db db = DbFactory.wrap(ds);  // wrap DataSource with mJDBC wrapper.\n    MySqlQueries q = db.attachSql(MySqlQueries.class) // attach query interface. All queries are parsed and validated at this moment.\n    User user = q.getUserByLogin('login'); // run any query method\n```\nwhere MySqlQueries:\n```java\npublic interface MySqlQueries {\n    @Sql(\"SELECT * FROM users WHERE login = :login\")\n    User getUserByLogin(@Bind(\"login\") String login)\n}\n```\nAn example of simple and fast pooled data source is [HikariCP](https://github.com/brettwooldridge/HikariCP). \n\n##### Transactions\nTo run multiple SQL queries within a single transaction create a dedicated dbi (db-interface) interface and attach it to database.\nIt will return a proxy class that will wrap all interface methods into transactions.\n```java\n    java.sql.DataSource ds = ...;\n    Db db = DbFactory.wrap(ds);\n    MyDbi dbi = db.attachDbi(MyDbiImpl(), MyDbi.class); // all MyDbi method calls will be proxied to MyDbiImpl wrapped with transactions.\n    User user = dbi.getUserByLoginCreateIfNotFound('login');\n```\nwhere MyDbi:\n```java\npublic interface MyDbi {\n    User getUserByLoginCreateIfNotFound(String login);\n}\n\npublic class MyDbiImpl implements MyDbi {\n    public User getUserByLoginCreateIfNotFound(String login) {\n        User user = myQueries.getUserByLogin(login);\n        if (user == null) {\n            User user = new User();\n            user.login = login;\n            user.id = myQueries.insertUser(user);\n        }\n        return user;\n    }\n}\n```\nNotes:\n * If Impl method is called directly with no use of proxy interface no new transaction is started. The method will share transaction context with an upper-stack method.\n Transaction is committed/rolled back when upper-stack method is finished.\n * All @Sql (raw SQL) methods are processed as independent transactions when no dbi interface is used.\n * No connection is allocated when Dbi method is called. The actual connection is requested from datasource only when first SQL statement is used. \n So if DBI method uses cache and do not create any statements at all -\u003e no network activity will be performed at all.\n\n\n\n##### Result set mappers\n\nExtend [DbMapper](https://github.com/mjdbc/mjdbc/blob/master/src/main/java/com/github/mjdbc/DbMapper.java) class.\nIt may be convenient to put the implementation into the Java class it maps [(example)](https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/asset/model/User.java).\n\n```java\n@Mapper\npublic static final DbMapper\u003cUser\u003e MAPPER = (r) -\u003e {\n    User user = new User();\n    user.id = new UserId(r.getInt(\"id\"));\n    user.login = r.getString(\"login\");\n    ...\n    return user;\n};\n```\n\nOptional: register this mapper during initialization;\n```java\n    Db db = DbFactory.wrap(ds);\n    db.registerMapper(User.class, User.MAPPER)\n```\nNow use User type in all queries attached to mJDBC database instance.\nMappers for native Java types are supported by default [(source)](https://github.com/mjdbc/mjdbc/blob/master/src/main/java/com/github/mjdbc/util/Mappers.java) and can be overridden if needed..\n\nNote: If mapper is not registered manually mJDBC will try to derive it searching for public static and final field of the mapped object annotated as @Mapper.\n\n##### Parameter binders\nParameters in @Sql interfaces can be bound with @Bind or @BindBean annotations.\n* @Bind maps single named parameter.\n* @BindBean maps all parameters from public fields or getters of the object passed as parameter.\n\nBinders for native Java types are supported by default [(source)](https://github.com/mjdbc/mjdbc/blob/master/src/main/java/com/github/mjdbc/util/Binders.java).\n\nIn most cases you do not need to create your own binder. All you need is to make your class to implement one of these interfaces: DbInt, DbLong or DbString [(example)](https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/asset/model/UserId.java).\n\n##### Low level API\nUsage of java.sql.* API is transparent in mJDBC. You can always get statements, connections, result sets and have a full power of native JDBC driver.\nExample:\n```java\nDb db = DbFactory.wrap(ds);\ndb.execute(c -\u003e { // wraps method into transaction\n    try (java.sql.Statement statement = c.createStatement()) {\n        ...\n    }\n});\n```\nIf named parameters or object/collections mappers support is needed:\n```java\nDb db = DbFactory.wrap(ds);\nUser user = db.execute(c -\u003e { // wraps method into transaction\n    DbPreparedStatement s = c.prepareStatement(c, \"SELECT * FROM users WHERE login = :login\", User.MAPPER)\n    s.setString(\"login\", login);\n\n    // Direct access to JDBC starts here\n    // JDBC supports parameter binding by index only. Here is the name -\u003e indexes mapping.\n    Map\u003cString, List\u003cInteger\u003e\u003e namedParametersMapping = s.parametersMapping;\n    // Original JDBC PreparedStatement\n    java.sql.PreparedStatement ps = s.statement;\n    ... // write some low-level code with java.sql.PreparedStatement: bind data streams, execute and check result set...\n\n    // or simply return the result using mapper class provided in DbPreparedStatement constructor.\n    return s.query();\n});\n```\n\nNote: that when you use [DbPreparedStatement](https://github.com/mjdbc/mjdbc/blob/master/src/main/java/com/github/mjdbc/DbPreparedStatement.java) class it is not necessary to close it manually.\nIt will be closed automatically when connection is closed (returned to pool). In this example  connection is closed when *db.execute()* method is finished.\n\n\n##### Timers\nFor all methods annotated with @Sql or Dbi interface methods mjdbc automatically collects statistics:\n* method invocation count\n* total time spent in the method in nanoseconds.\n\nCheck [checkTxTimer/checkSqlTimer](https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/SamplesTest.java) tests for details.\n\n\n##### More\nFor more examples check [unit tests](https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/) to see API in action.\n\nYou may also find useful to check the recommended way of writing [raw SQL interfaces](https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/asset/UserSql.java) and\n[transactional database interfaces](https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/asset/dbi/SampleDbi.java) in tests.\n\n\n### Requirements\n\nJava8+\n\n\n### License\nApache License 2.0\n\n### Related projects\n* [cs4j](https://github.com/cs4j/cs4j) - minimal Cron style task scheduler for Java compatible with Spring API\n* [μotto](https://github.com/uotto/uotto) - plain Java version of [Otto Event Bus](https://github.com/square/otto) with no dependencies\n* [openjson](https://github.com/openjson/openjson) - fast and minimal JSON library for Java  [OpenJSON](https://github.com/openjson/openjson) under Apache 2 license.\n\n### Projects that use mJDBC\n* [zametki](https://github.com/zametki/zametki) - simple alternative to Evernote. See  [sql](https://github.com/zametki/zametki/tree/master/src/main/java/com/github/zametki/db/sql) package for details.\n* [pesennik](https://github.com/pesennik/pesennik) - songbook. See  [sql](https://github.com/pesennik/pesennik/tree/master/src/main/java/com/github/pesennik/db/sql) package for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjdbc%2Fmjdbc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmjdbc%2Fmjdbc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjdbc%2Fmjdbc/lists"}