【问题标题】:Separating SQL from the Java Code将 SQL 与 Java 代码分离
【发布时间】:2012-06-03 18:45:25
【问题描述】:

这是我必须连接数据库时经常遇到的问题;如何将 SQL 与普通的 java 代码分开?我通常为数据库连接使用单独的类,但是,当您有多个数据库和每个数据库中的多个表时,总是很难做到 100%

例如,如果我们想将所有 java SQL 放在一个名为 DBConnector.java 的类中,我们如何为不同的插入、删除、数据检索等进行通用编码?我认为理想情况是所有 SQL 语句都应该在同一个类中,并且应该与数据库应用程序范围内的不同风格的相同操作兼容,从而提供与其余代码的逻辑分离。

public void insertData (String db, String table, <Whatever Fields to be Inserted>)
{
  //generic SQL INSERT statement and execution 
}

public ResultSet retrieveData (String db, String table, <Whatever Fields Relevant>) 
{
  //generic retrieval of data
}

有没有办法做到这一点?还是我们应该只为不同风格的插入、查询等添加功能?

谢谢!

【问题讨论】:

    标签: java sql database


    【解决方案1】:

    如果您想要一个健全的架构,您至少需要几层来分离关注点。

    首先,从模型类开始(大多数情况下,您需要为数据库中的每个表创建一个)。自己编写它们,或者使用 ORM(例如 EclipseLink、Hibernate)自动生成它们。这些应该是 POJO(普通旧 Java 对象),这意味着它们是具有属性的 simple 对象(例如,字符串类型的 Name、整数类型的 Id 等)。您的模型对象应该是数据的载体,仅此而已(当然没有逻辑或处理)。

    然后,为所有模型类创建 DAO(数据访问对象)(如果需要,您可以构建一个 GenericDao 类来继承)。在这里,您将通过将 model 对象作为参数的方法提供 CRUD 操作(插入、更新、删除)。这是特定于数据库后端的,尽管您可以根据需要插入与数据库无关的 DAO 层。

    第三,每个逻辑类组有一个 servicemanager 层(这是所有前端和控制器代码都应该与所有想要的功能对话的层)。一个典型的方法可以称为registerCustomer(...)(可能使用不同的 DAO 类)。或findCustomerByName()等。

    以这种方式构建您的应用程序称为MVC(模型 - 视图 - 控制器),因此如果您想了解更多信息,请在 Google 上使用该术语。

    这样,您通常不会有高于 DAO 层的 SQL 查询,这意味着您的应用程序 a) 可维护 b) 以后更容易更改后端。

    【讨论】:

    • 感谢您提供一般而详细的答案。我正在寻找独立于技术的解决方案。
    【解决方案2】:

    伊扎, 这里有关于将 SQL 与 Java 代码分离的讨论:Java - Storing SQL statements in an external file 您的解决方案是可以理解的,但是如果查询不是标准的(例如,不仅仅是 a = 10 的位置,而是包含在 (...) 或 group by 中,所以我建议您避免使用它。 当您在 Java 中使用 DB 时,为了最大限度地减少样板代码,您应该使用 Spring JDBC。你也可以使用 Hibernate,如果它在你的情况下是可以接受的,它可以让你避免一些 sql 的使用。

    【讨论】:

      【解决方案3】:

      最好的方法是使用Hibernate,它现在是行业标准。

      简而言之,它生成所需的 SQL,代码处理表示行的 java 对象。如果您调用 setter,Hibernate 会计算出完成更新所需的 SQL。

      对于 getter,您的代码可能如下所示:

      shoppingCart.getCustomer().getCountry().getCode();
      

      Hibernate 计算出通过customer 表从shopping_cart 表到country 表所需的SQL 连接。

      它真的很棒,值得过渡。

      【讨论】:

      • 我不会这么直截了当地说 Hibernate 是 最佳 选项。例如,MyBatis 是这个问题的轻量级替代方案,它以更快、更容易理解(更不用说幕后“魔术”)的方式解决了这个问题。
      • 这不是问题的答案,向想编写 SQL 的人推荐 ORM 就像在有人寻求如何烘焙蛋糕的帮助时告诉他们买蛋糕。
      • 是的,例如,我正在做一个课堂项目。如果我提交 Hibernate 代码而不是 PreparedStatements,我肯定会得到一个 F.
      • @michael 我不知道。使用标准库是正常且最好的方法。除非您被告知不允许使用特定资源,否则您应该按照行业的做法行事。
      • @Bohemian 很遗憾,这是一个 SQL 类。
      【解决方案4】:

      你应该使用一些DAOFactory,这个类用于获取连接。 为了反映数据库中的表,您应该创建代表实体的DTO - Data Tranfer Objects。因此,如果您有表User,只需创建带有属性、getter 和 setter 的UserDTO.java。与数据库通信的类是DAO - Data Access Object。您应该只在此处创建用于从数据库中获取数据的 SQL 语句和方法。 首先是精心设计的结构。这样您的代码就会变得更干净、更快速、更安全。我建议您创建自己的ORM。 所以,看看不同的框架并进行一些测试


      EasyORM

      double count = 0;
      TransDB trans = new TransDB() ;
      List<Trans> list = new ArrayList<Trans>();
      list = trans.getAll();
      for (Trans element : list)
      {
      count+= element.getData();
      }
      ...
      

      休眠

      double count = 0;
      Session session = null;
      List<Trans> list = new ArrayList<Trans>();
      list = HibernateUtil.getSessionFactory().openSession();
      list = (List<Trans>) session
      .createQuery("from Trans").list();
      for (Trans element : list)
      {
      count += element.getData().doubleValue();
      }
      ...
      

      然后比较??

      评估(以毫秒为单位)

      EasyORM: MySQL:初始化 - 6344,平均 - 4868 MS SQL:初始化 - 8126,平均 - 6752

      休眠: MySQL:初始化 - 27406,平均 - 23728 MS SQL:初始化 - 28605(+250%),平均 - 24912

      所以你自己的ORM 实际上是从SQL script 生成的,比Hibernate(到10)要快,为什么?通过在层间插入肯定不能去提高吞吐量。这只是一项测试,我还有其他测试。 所以对我来说,我建议您创建自己的ORM,这里还有一些缺点,例如时间消耗或使用有问题的更改DMS,但作为对生成命令的完全控制的优势,您可以使用特定于特定DMS 的功能(ORDM、特殊命令等)。所以我不认为Hibernate 是最好的,真的不是。

      【讨论】:

      • don't use automated frameworks as Hibernate - 对不起,这个说法是错误的。阅读一些关于 MyBatis 的内容(例如)。基本上,它是一个 SQL 模板引擎。所以,就像在 JSP 中一样,你创建一个视图,并将变量传递给它,你创建 MyBatis “SQL 模板”,并将变量传递给它们。非常轻巧有效。另外我敢肯定还有其他类似的解决方案。
      • 但我仍然坚持认为你的 owm ORM 比 Hibernate ok EclipseLink 快得多,所以我不知道为什么我的帖子在真实时被否决(除了我编辑的错误,抱歉) 我认为首先是你的 IS 的性能和速度。
      • 不,性能和速度不是重中之重。牺牲一些性能是值得的,以防它使您的代码更具可读性和组织性 - 这会导致未来的错误和拼写错误更少。当然,编写自己的 DAO 层很简洁,但每次你必须用一些新方法扩展它时,你会因为这个决定而讨厌自己。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      • 1970-01-01
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 1970-01-01
      • 2012-07-31
      相关资源
      最近更新 更多