简单的 jdbc 包装器

发布于 2024-07-09 05:56:35 字数 399 浏览 12 评论 0原文

为了在我们的应用程序中实现数据访问代码,我们需要一些框架来包装 jdbc(由于可扩展性,ORM 不是我们的选择)。

我曾经使用过的最酷的框架是 Spring-Jdbc。 然而,我公司的政策是避免外部依赖,尤其是spring、J2EE等。 所以我们正在考虑编写自己的手工制作的jdbc框架,其功能类似于Spring-jdbc:行映射,错误处理,支持java5的功能,但不支持事务。

有人有编写这样的 jdbc 包装框架的经验吗? 如果有人有使用其他 jdbc 包装框架的经验,请分享您的经验。

提前致谢。

To implement data access code in our application we need some framework to wrap around jdbc (ORM is not our choice, because of scalability).

The coolest framework I used to work with is Spring-Jdbc. However, the policy of my company is to avoid external dependencies, especially spring, J2EE, etc.
So we are thinking about writing own handy-made jdbc framework, with functionality similar Spring-jdbc: row mapping, error handling, supporting features of java5, but without transaction support.

Does anyone have experience of writing such jdbc wrapper framework?
If anyone has experience of using other jdbc wrapper frameworks, please share your experience.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

罗罗贝儿 2024-07-16 05:56:35

我们编写了自己的包装器。 这个主题值得写一篇论文,但我怀疑我是否有时间来写它,所以这里有一些关键点:

  • 我们拥抱 SQL 并且没有试图隐藏它。 唯一的调整是添加对命名参数的支持。 参数很重要,因为我们不鼓励使用即时 sql(出于安全原因)并且我们始终使用PreparedStatements。

  • 对于连接管理,我们使用 Apache DBCP。 这在当时很方便,但尚不清楚现代 JDBC 实现需要多少(缺乏关于这方面的文档)。 DBCP 还池化PreparedStatements。

  • 我们没有考虑行映射。 相反(对于查询)我们使用了类似于 Apache dbutil 的 ResultSetHandler 的东西,它允许您将结果集“馈送到”一个方法中,然后该方法可以将信息转储到您想要的任何地方。 这样更加灵活,实际上实现一个用于行映射的 ResultSetHandler 并不难。 对于插入/更新,我们创建了一个通用记录类(基本上是一个带有一些额外功能的哈希图)。 行映射的最大问题(对我们来说)是,一旦执行“有趣的”查询,您就会陷入困境,因为您可能有映射到不同类的字段; 因为你可能有一个分层的类结构,但有一个扁平的结果集; 或者因为映射很复杂并且依赖于数据。

  • 我们内置了错误日志记录。 对于异常处理:在查询中,我们捕获并记录,但对于更新,我们捕获、记录并重新抛出未经检查的异常。

  • 我们使用包装器方法提供事务支持。 调用者提供执行事务的代码,我们确保事务得到正确管理,不会忘记完成事务,并且内置回滚和错误处理。

  • 后来,我们添加了一个非常简单的关系方案,允许单个更新/插入应用于记录及其所有依赖项。 为了简单起见,我们没有在查询中使用它,并且我们特别决定不支持删除,因为使用级联删除更可靠。

迄今为止,该包装器已成功用于两个项目。 当然,它是轻量级的,但现在每个人都说他们的代码是轻量级的。 更重要的是,它提高了程序员的生产力,减少了错误的数量(并使问题更容易追踪),并且如果需要的话,它相对容易追踪,因为我们不相信仅仅为了提供漂亮的架构而添加大量层。

We wrote our own wrapper. This topic is worthy of a paper but I doubt I'll ever have time to write it, so here are some key points:

  • we embraced sql and made no attempt to hide it. the only tweak was to add support for named parameters. parameters are important because we do not encourage the use of on-the-fly sql (for security reasons) and we always use PreparedStatements.

  • for connection management, we used Apache DBCP. This was convenient at the time but it's unclear how much of this is needed with modern JDBC implementations (the docs on this stuff is lacking). DBCP also pools PreparedStatements.

  • we didn't bother with row mapping. instead (for queries) we used something similar to the Apache dbutil's ResultSetHandler, which allows you to "feed" the result set into a method which can then dump the information wherever you'd like it. This is more flexible, and in fact it wouldn't be hard to implement a ResultSetHandler for row mapping. for inserts/updates we created a generic record class (basically a hashmap with some extra bells and whistles). the biggest problem with row mapping (for us) is that you're stuck as soon as you do an "interesting" query because you may have fields that map to different classes; because you may have a hierarchical class structure but a flat result set; or because the mapping is complex and data dependent.

  • we built in error logging. for exception handling: on a query we trap and log, but for an update we trap, log, and rethrow an unchecked exceptions.

  • we provided transaction support using a wrapper approach. the caller provides the code that performs transaction, and we make sure that the transaction is properly managed, with no chance of forgetting to finish the transaction and with rollback and error handling built-in.

  • later on, we added a very simplistic relationship scheme that allows a single update/insert to apply to a record and all its dependencies. to keep things simple, we did not use this on queries, and we specifically decided not to support this with deletes because it is more reliable to use cascaded deletes.

This wrapper has been successfully used in two projects to date. It is, of course, lightweight, but these days everyone says their code is lightweight. More importantly, it increases programmer productivity, decreases the number of bugs (and makes problems easier to track down), and it's relatively easy to trace through if need be because we don't believe in adding lots of layers just to provide beautiful architecture.

终陌 2024-07-16 05:56:35

Spring-JDBC 太棒了。 考虑一下,对于像 Spring 这样的开源项目,外部依赖的负面影响被最小化。 您可以采用满足您的 JDBC 抽象要求的最稳定的 Spring 版本,并且您知道,如果您遇到问题,您始终能够自行修改源代码,而无需依赖外部方。 您还可以检查您的组织可能对外部方编写的代码存在的任何安全问题的实施情况。

Spring-JDBC is fantastic. Consider that for an open source project like Spring the down side of external dependency is minimized. You can adopt the most stable version of Spring that satisfies your JDBC abstraction requirements and you know that you'll always be able to modify the source code yourselves if you ever run into an issue -- without depending on an external party. You can also examine the implementation for any security concerns that your organization might have with code written by an external party.

夜血缘 2024-07-16 05:56:35

我更喜欢的一个:Dalesbred。 它获得了麻省理工学院的许可。

获取自定义类(部门)的所有行的简单示例。

List<Department> departments = db.findAll(Department.class,
    "select id, name from department");

当自定义类定义为:

public final class Department {
    private final int id;
    private final String name;

    public Department(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

免责声明:它是由我工作的公司定义的。

The one I prefer: Dalesbred. It's MIT licensed.

A simple example of getting all rows for a custom class (Department).

List<Department> departments = db.findAll(Department.class,
    "select id, name from department");

when the custom class is defined as:

public final class Department {
    private final int id;
    private final String name;

    public Department(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

Disclaimer: it's by a company I work for.

窝囊感情。 2024-07-16 05:56:35

这听起来是一个非常短视的决定。 考虑开发/维护这样一个框架的成本,特别是当你可以获得它并且它的源代码是免费的时。 您不但不用自己开发,还可以根据需要随意修改。

话虽如此,您真正需要复制的是 JdbcTemplate 的概念及其回调(PreparedStatementCreator、PreparedStatementCallback)以及 RowMapper/RowCallbackHandler。 编写这样的内容不应该过于复杂(特别是考虑到您不必进行事务管理)。

然而,正如我所说,当您可以免费获得它并根据您认为合适的方式修改源代码时,为什么还要编写它呢?

This sounds like a very short sighted decision. Consider the cost of developing/maintaining such a framework, especially when you can get it, and it's source code for free. Not only do you not have to do the development yourself, you can modify it at will if need be.

That being said, what you really need to duplicate is the notion of JdbcTemplate and it's callbacks (PreparedStatementCreator, PreparedStatementCallback), as well and RowMapper/RowCallbackHandler. It shouldn't be overcomplicated to write something like this (especially considering you don't have to do transaction management).

Howver, as i've said, why write it when you can get it for free and modify the source code as you see fit?

踏月而来 2024-07-16 05:56:35

尝试 JdbcSession来自 jcabi-jdbc。 它就像 JDBC 应该的那样简单,例如:

String name = new JdbcSession(source)
  .sql("SELECT name FROM foo WHERE id = ?")
  .set(123)
  .select(new SingleOutcome<String>(String.class));

就是这样。

Try JdbcSession from jcabi-jdbc. It's as simple as JDBC should be, for example:

String name = new JdbcSession(source)
  .sql("SELECT name FROM foo WHERE id = ?")
  .set(123)
  .select(new SingleOutcome<String>(String.class));

That's it.

凉薄对峙 2024-07-16 05:56:35

尝试使用我的库作为替代方案:

<dependency>
  <groupId>com.github.buckelieg</groupId>
  <artifactId>jdbc-fn</artifactId>
  <version>0.2</version>
</dependency>

更多信息此处

Try mine library as alternative:

<dependency>
  <groupId>com.github.buckelieg</groupId>
  <artifactId>jdbc-fn</artifactId>
  <version>0.2</version>
</dependency>

More info here

屌丝范 2024-07-16 05:56:35

Jedoo

有一个名为 Jedoo 的包装类,它使用数据库连接池和单例模式来访问它作为共享变量。 它有很多函数可以快速运行查询。

用法

要使用它,您应该将其添加到您的项目中并在 java 类中加载其单例:

import static com.pwwiur.util.database.Jedoo.database;

并且使用它也非常简单:

if(database.count("users") < 100) {
    long id = database.insert("users", new Object[][]{
        {"name", "Amir"},
        {"username", "amirfo"}
    });
    
    database.setString("users", "name", "Amir Forsati", id);

    try(ResultSetHandler rsh = database.all("users")) {
         while(rsh.next()) {
             System.out.println("User ID:" + rsh.getLong("id"));
             System.out.println("User Name:" + rsh.getString("name"));
         }
    }
}

您还可以在上面链接的文档中找到一些有用的函数。

Jedoo

There is a wrapper class called Jedoo out there that uses database connection pooling and a singleton pattern to access it as a shared variable. It has plenty of functions to run queries fast.

Usage

To use it you should add it to your project and load its singleton in a java class:

import static com.pwwiur.util.database.Jedoo.database;

And using it is pretty easy as well:

if(database.count("users") < 100) {
    long id = database.insert("users", new Object[][]{
        {"name", "Amir"},
        {"username", "amirfo"}
    });
    
    database.setString("users", "name", "Amir Forsati", id);

    try(ResultSetHandler rsh = database.all("users")) {
         while(rsh.next()) {
             System.out.println("User ID:" + rsh.getLong("id"));
             System.out.println("User Name:" + rsh.getString("name"));
         }
    }
}

There are also some useful functions that you can find in the documentation linked above.

折戟 2024-07-16 05:56:35

mJDBC: https://mjdbc.github.io/

我使用它多年,发现它非常有用(我是这个库的作者)。

它受到 JDBI 库的启发,但没有依赖项,添加了事务支持,提供性能计数器,并允许在您确实需要时轻松切换到 Java 中尽可能低的 SQL 级别(旧的普通 JDBC API)。

mJDBC: https://mjdbc.github.io/

I use it for years and found it very useful (I'm the author of this library).

It is inspired by JDBI library but has no dependencies, adds transactions support, provides performance counters and allows to switch to the lowest possible SQL level in Java (old plain JDBC API) easily in case if you really need it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文