将行数据从SQL数据映射到Java对象

我有一个Java类,其实例字段(和匹配的setter方法)匹配SQL数据库表的列名。 我想优雅地从表中获取一行(到ResultSet中)并将其映射到该类的实例。

例如:

我有一个“学生”类,其实例字段为“FNAME”,“LNAME”,“GRADE”,并为每个实例提供适当的getter和setter方法。

我还有一个SQL表,其中包含三个同名的列。

现在我正在做这样的事情:

rs = statement.executeQuery(query); Student student = new Student(); student.setFNAME(rs.getString("FNAME")); student.setLNAME(rs.getString("LNAME")); student.setGRADE(rs.getString("GRADE")); 

必须有一个不那么冗长的方式,对吧? 当我添加列时,这可能会变得非常烦人和混乱。

我建议使用Spring JDBC 。 您不需要使用Spring的其余部分来使用他们的JDBC库。 它将为您管理连接(不再关闭ConnectionStatementResultSet )并具有许多便利,包括行映射。

我们用Spring JDBC改进遗留代码并没有什么问题。

以下是Spring JDBC概述的演示文稿(PDF)。 虽然没有让Spring注入依赖项,但它已经存在了几年,但仍然基本相同。

Spring JDBC Presentation PDF

您可以通过执行以下简单方法来执行此操作:

用作方法指针的接口:

 public interface I_DBtoJavaObjectConvertable { public T createFromDB(ResultSet i_rs) throws SQLException; } 

处理从SQL到java Object的每个映射的通用类:

 public class DBManager { static volatile Connection conn; //set here a static c'tor to handle the connection to the database //The General generic method: public static  List GetObjectsFromDB(String i_Query, I_DBtoJavaObjectConvertable i_Converter) { List ResList = new ArrayList<>(); try { Statement st = conn.createStatement(); for (ResultSet rs = st.executeQuery(i_Query); rs.next();) { ResList.add((T) i_Converter.createFromDB(rs)); } } catch (SQLException ex) { _LOG_ERROR(ex.getMessage()); } return ResList; } } 

现在通过使用Lanbda表达式,可以通过给定转换方法轻松地将sql行转换为对象,例如:

 public static User FetchUserFromDB(ResultSet i_rs) { User userToCreate = null; try { String FirstName = i_rs.getString("FirstName"); String LastName = i_rs.getString("LastName"); String Password = i_rs.getString("Password"); userToCreate = new User(FirstName, LastName, Password); } catch (SQLException ex) { _LOG_ERROR("Error in fetching user from DB: \n" + ex.getMessage()); } return userToCreate; } 

现在你可以使用这个方法带来你想要的任何用户:

 public static List GetAllUsersFromDB() throws SQLException { String Query = "select * " + "from UsersTable"; return DBManager.GetObjectsFromDB(Query, rs -> FetchUserFromDB(rs)); } 

要么:

 public static List GetAllNamesFromDB() throws SQLException { String Query = "select FirstName " + "from UsersTable"; return DBManager.GetObjectsFromDB(Query, rs -> rs.getString("FirstName")); } 

您可以像使用一个JPA提供程序一样使用ORM,例如Hibernate 。 这使您可以设置对象和表之间的映射。

如果您使用JDBC,它的工作方式。 如果您想避免在Java中添加这样的列,您可以考虑使用一些ORM框架。

稍微简单一点的方法是给Student一个接受3个字符串的构造函数。 然后你可以这样做:

 Student student = new Student(rs.getString("FNAME"), rs.getString("LNAME"), rs.getString("GRADE")); 

另一种方法是使用像Hibernate这样的ORM,但是对于处理大量表格的大型项目而言,Hibernate只值得大量设置工作。

有许多ORM库可以简化或消除JDBC苦差事。 有关示例,请参阅Source Forge ORM 。 我喜欢我的库, sormula ,因为它可以用于最小配置。

如果您不想使用任何其他框架,则可以创建标准映射方法并在每个Result之后使用它

 public class CurrencyDAO(){ public Currency findById(int id) { String sql = "SELECT * FROM CCR.CURRENCY WHERE id = ?"; Currency currency = null; Connection c = null; try { c = DBConnection.getConnection(); PreparedStatement ps = c.prepareStatement(sql); ps.setInt(1, id); ResultSet rs = ps.executeQuery(); if (rs.next()) { currency = processRow(rs); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally { DBConnection.close(c); } return currency; } protected Currency processRow(ResultSet rs) throws SQLException { Currency currency = new Currency(); currency.setId(rs.getInt("id")); currency.setEUR(rs.getString("EUR")); currency.setUSD(rs.getString("USD")); currency.setRate(rs.getString("rate")); return currency; } } 

试试q2o吧。 它是一个基于JPA的对象映射器,它可以帮助您完成许多繁琐的SQL和JDBC ResultSet相关任务,但没有ORM框架带来的所有复杂性。

将Student类绑定到其对应的表:

 @Table(name = "STUDENTS") public class Student ( private String FNAME; private String LNAME; private String GRADE; ... ) 

按成绩选择一些学生:

 List students = Q2ObjList.fromClause(Student.class, "GRADE = ?", grade); 

更改学生的成绩并将更改保留到数据库:

 student.setGRADE(grade); Q2obj.update(student); 

即使依赖Spring JDBC,q2o也很有用:

 jdbcTemplate.queryForObject("...", new RowMapper() { @Override public Student mapRow(final ResultSet rs, final int rowNum) throws SQLException { return Q2Obj.fromResultSet(rs, Student.class); } }); 

这很容易,不是吗? 在此处查找有关q2o的更多信息。