3

我有以下功能:

public Map<Integer, Product> fetchAllProducts() {

  Map<Integer, Product> pArr = new HashMap();
  try {
     Statement st = conn.createStatement();
     ResultSet rs = st.executeQuery("SELECT id, intro, content, price FROM Product");
     while (rs.next()) {
       pArr.put(rs.getInt("id"), new Product(rs));
     }
     st.close();
  } catch (SQLException ex) {
   //...
  }
  return pArr;
}

它从 mySQL 表中获取所有行,Product并为每一行创建一个新Product类。产品构造器:

 public Product(ResultSet rs) {
    try {
       price = rs.getInt("price");
       content = rs.getString("content");
       intro = rs.getString("intro");
    } catch (SQLException ex) {
       //...
    }
   }

我的问题是:有没有更好的方法将结果列分配给变量Product?代码price = rs.getInt("price");等似乎是多余的,不是吗?完美的是,如果我将查询语句更改SELECT intro, content, tax, delivery FROM ...为构造函数,则会自动将其分配给构造函数中的适当变量(即介绍、内容、税收、交付)。这可以用Java完成还是我只是在做梦?

4

5 回答 5

3

第一:你真的不应该将 传递ResultSetProduct! 您应该清楚地将数据库访问代码与业务逻辑分开。

所以通常我希望在您的代码中看到这一点:

private static final String TABLE_NAME = "product";
private static final String ID_COLUMN = "id";
private static final String INTRO_COLUMN = "intro";
private static final String CONTENT_COLUMN = "content";
private static final String PRICE_COLUMN = "price";

private static final String FETCHALLPRODUCTS_QUERY = String.format("SELECT %s, %s, %s, %s FROM %s", ID_COLUMN, INTRO_COLUMN, CONTENT_COLUMN, PRICE_COLUMN, TABLE_NAME);

public Map<Integer, Product> fetchAllProducts() {

  Map<Integer, Product> pArr = new HashMap();
  try {
     Statement st = conn.createStatement();
     ResultSet rs = st.executeQuery(FETCHALLPRODUCTS_QUERY);
     while (rs.next()) {
        Integer price = rs.getInt(PRICE_COLUMN);
        String content = rs.getString(CONTENT_COLUMN);
        String intro = rs.getString(INTRO_COLUMN);

        Product product = new Product(price, content, intro);
        Integer id = rs.getInt(ID_COLUMN);
        pArr.put(id, product);
     }
     st.close();
  } catch (SQLException ex) {
   //...
  }
  return pArr;
}

但是要回答您的问题:在处理普通 JDBC 时,这样做是一种非常常见的做法。您正在寻找的是像Hibernate这样的ORM框架。

使用 JDBC 连接时我正在做的一件事是为列名和表名声明常量。这样在我看来它更干净一些。

于 2012-04-27T07:54:25.430 回答
3

您可以在 Reflection 的帮助下实现这一点,ResultSetMapper也是如此。

一个教程

Apache BeanUtils 有类似的东西,但它返回给你DynaBean

如果您可以迁移到更复杂和完整的系统,您应该考虑使用 ORM,如 hibernate、JPA。

对于普通的 JDBC,您可以使用自己的反射工具,也可以使用 ResultMapper。

于 2012-04-27T08:00:13.560 回答
0

我认为如果您使用例如hibernate,这是可能的。但就像我的前身写的那样:不要在 Product 的构造函数中设置 ResultSet,因为您将处理 ResultSet 的另一个副本(ResultSet 很重),并且如果您有很多数据,那会降低性能。

所以就这样做:

...

pArr.put(rs.getInt("id"), new Product(rs.getint("Price") ....));

...

public Product(int price ....) {
于 2012-04-27T08:01:23.277 回答
0

我猜想使用一些或映射库(如 Hibernate)会使代码更愉快。正如我听说的那样,它使您想要的东西变得普遍。但是,使用它涉及替换项目中的所有数据库交互代码。我认为您的代码并没有那么难看,可能这样做会使它更令人愉快:

 while (rs.next()) {
   pArr.put(rs.getInt("id"), new Product(rs));
   Integer id = rs.getInt("id");
   Integer price = rs.getInt("price");
   Integer content = rs.getString("content");
   Integer intro = rs.getString("intro");
   Product product = new Product(price, content, intro);
   pArr.put(id, product);
 }

嗯,似乎在我输入答案时出现了三个相同的答案。对不起大家 :)

于 2012-04-27T08:10:34.750 回答
0

Commons DbUtils是 JDBC 上的一个薄层(不像 Hibernate 那样复杂),可以从 ResultSet 设置 bean 属性

于 2012-04-27T08:15:52.877 回答