Java 从resultset创建对象。我这样做对吗?

Java 从resultset创建对象。我这样做对吗?,java,jdbc,resultset,Java,Jdbc,Resultset,我正在学习Java,现在正在学习JDBC。我想我已经掌握了如何使用resultset对象,但我想确保我做得正确 请参阅下面的代码。它在名为“restaurant”的数据库中查询名为“menu”的表。该表有四列: id\u菜单整数,表的主键 名称字符串,菜单项的名称(例如“双芝士汉堡”) 描述字符串,菜单项的描述(例如“全麦面包上的两个全牛肉饼”) 价格加倍,物品的价格(例如5.95)(注意我知道我可以使用货币类型,但我尽量保持简单) 下面是menuItem对象的Java代码。表中的每一行都应

我正在学习Java,现在正在学习JDBC。我想我已经掌握了如何使用resultset对象,但我想确保我做得正确

请参阅下面的代码。它在名为“restaurant”的数据库中查询名为“menu”的表。该表有四列:

  • id\u菜单整数,表的主键
  • 名称字符串,菜单项的名称(例如“双芝士汉堡”)
  • 描述字符串,菜单项的描述(例如“全麦面包上的两个全牛肉饼”)
  • 价格加倍,物品的价格(例如5.95)(注意我知道我可以使用货币类型,但我尽量保持简单)
下面是menuItem对象的Java代码。表中的每一行都应用于创建menuItem对象:

public class menuItem {

    public int id = 0;
    public String descr = "";
    public Double price = 0.0;
    public String name = "";
    public menuItem(int newid, String newdescr, Double newprice, String newname){
        id = newid;
        descr = newdescr;
        price = newprice;
        name = newname;
        }
    }
一切都是公开的,只是为了简化这个练习

下面是填充数据库的代码。目前,这段代码是主类中的一个方法

public static ArrayList<menuItem> reQuery() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException{    

    ArrayList<menuItem> mi = new ArrayList<menuItem>();

    //Step 1. User Class.forname("").newInstance() to load the database driver.
    Class.forName("com.mysql.jdbc.Driver").newInstance();

    //Step 2. Create a connection object with DriverManager.getConnection("")
    //Syntax is jdbc:mysql://server/database? + user=username&password=password
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/miguelel_deliveries?" + "user=root&password=");

    //Step 3. Create a statement object with connection.createStatement();
    Statement stmt = conn.createStatement();

    //Step 4. Create variables and issue commands with the Statement object.
    ResultSet rs = stmt.executeQuery("Select * from menu");

    //Step 5. Iterate through the ResultSet. Add a new menuItem object to mi for each item.
    while(rs.next()){
    menuItem item = new menuItem(rs.getInt("id_menu"),rs.getString("descr"),rs.getDouble("price"),rs.getString("name"));
    mi.add(item);
    }
    return mi;
}
publicstaticarraylistrequery()抛出ClassNotFoundException、InstantiationException、IllegalAccessException、SQLException{
ArrayList mi=新的ArrayList();
//步骤1.User Class.forname(“”.newInstance()加载数据库驱动程序。
Class.forName(“com.mysql.jdbc.Driver”).newInstance();
//步骤2.使用DriverManager.getConnection(“”)创建连接对象
//语法是jdbc:mysql://server/database? +用户=用户名&密码=密码
Connection conn=DriverManager.getConnection(“jdbc:mysql://localhost/miguelel_deliveries?“+”user=root&password=“);
//步骤3.使用connection.createStatement()创建语句对象;
语句stmt=conn.createStatement();
//步骤4.使用语句对象创建变量并发出命令。
ResultSet rs=stmt.executeQuery(“从菜单中选择*);
//步骤5.遍历ResultSet。为每个项目向mi添加一个新的menuItem对象。
while(rs.next()){
menuItem item=new menuItem(rs.getInt(“id_menu”)、rs.getString(“descr”)、rs.getDouble(“price”)、rs.getString(“name”);
增加(项目);
}
返回mi;
}
这个代码有效。最后我得到了一个menuItem的ArrayList,这样每个元素都对应于表中的一行。但这是最好的办法吗?我可以将其概括为一种处理结果集的方法吗

  • 对于数据库中的每个表或视图,创建一个Java类,其属性相当于表的列

  • 将表内容加载到ResultSet对象中

  • 使用while(ResultSet.next())迭代ResultSet,在步骤1中为ResultSet中的每个项创建一个新对象(来自类)

  • 创建每个新对象时,将其添加到类的ArrayList中

  • 根据需要操纵ArrayList


  • 这是一种有效的方法吗?有更好的方法吗?

    代码逻辑很好,但实现中有几个问题:

    • 它不尊重命名约定。类以大写字母开头
    • 你不应该使用公共字段。如果构造函数在初始化之后立即重新初始化字段,则将字段初始化为默认值是无用的
    • 您没有关闭连接,这意味着每次执行该方法时,它都会保留一个打开的连接,导致内存被免费占用,并且由于达到最大打开连接数,您的程序最终会失败。应该在finally块中关闭连接,或者使用自Java7以来可用的try-with-resources构造。结果集和语句也应该关闭,尽管不关闭它们不像不关闭连接那样有问题
    • 对于足够新的驱动程序和JVM,类.forName().newInstance()应该不是必需的
    • 选择的类型很奇怪。例如,价格存储在可为空的双变量中。但是您可以使用getDouble()来获取其值,它永远不会返回null。此外,使用double作为价格是一个糟糕的选择。改用BigDecimal
    • 使用
      select*
      是一种不好的做法。选择所需的列,而不是所有列
    我不会概括每个表创建一个类。很多时候,您不会查询单个表中的所有列,而是查询多个联接表中的某些列


    <>我也会考虑使用ORM(JPA)来代替JDBC。这将使您的代码更干净、更简短、可读性更强、更安全。

    这属于感谢。我甚至不知道代码审查在那里。我准备了另外三个问题,都是“这段代码有效,但它是最好的方法吗”,就像这个问题一样。我将在代码复查时发布它们,而不是堆栈溢出。请随意结束这个问题,再次感谢。非常感谢。这些评论很有帮助。回复:我将menuItem重命名为menuItem。我将把公共属性更改为private并添加getter方法(我想我不需要setter?关闭时,我需要关闭连接、语句和结果集吗?还是conn.close()关闭语句和结果集?我注释掉了类。forName().newInstace()我想知道为什么我的Java教科书(Big Java,第四版,2010年起)表示这是必需的。再次感谢您提供的非常有用的注释。这是很久以前需要的。现在有了一种机制,允许jar定义JDBC驱动程序并向驱动程序管理器注册,而不需要任何代码。关闭连接是必要的。一旦不再需要它们,就关闭另外两个是一种很好的做法。在实际代码中,有时在同一连接上打开多个语句和结果集。关闭它们可释放内存和其他资源。