将JDBC ResultSet映射到对象

Qua*_*qai 27 java mysql jdbc resultset object

我有一个具有16个属性的用户类,如firstname,lastname,dob,username,password等...这些都存储在MySQL数据库中,当我想检索用户时,我使用ResultSet.我想将每个列映射回用户属性,但我这样做的方式看起来非常低效.例如我在做:

//ResultSet rs;
while(rs.next()) {
   String uid = rs.getString("UserId");
   String fname = rs.getString("FirstName");
   ...
   ...
   ...
   User u = new User(uid,fname,...);
   //ArrayList<User> users 
   users.add(u);
} 
Run Code Online (Sandbox Code Playgroud)

即我检索所有列,然后通过将所有列值插入到用户构造函数中来创建用户对象.

有谁知道更快,更整洁,这样做的方式?

Leo*_*Leo 49

如果您不想使用任何JPA提供程序,例如openJPA或hibernate,您可以尝试使用apache dbutils.

http://commons.apache.org/proper/commons-dbutils/examples.html

那么你的代码看起来就像这样

QueryRunner run = new QueryRunner(dataSource);

// Use the BeanListHandler implementation to convert all
// ResultSet rows into a List of Person JavaBeans.
ResultSetHandler<List<Person>> h = new BeanListHandler<Person>(Person.class);

// Execute the SQL statement and return the results in a List of
// Person objects generated by the BeanListHandler.
List<Person> persons = run.query("SELECT * FROM Person", h);
Run Code Online (Sandbox Code Playgroud)

  • 似乎是没有任何框架的纯 jdbc 逻辑的完美解决方案。凉爽的 !+1 (2认同)

Sho*_*ate 14

无需将resultSet值存储到String中并再次设置为POJO类.而是在您检索时设置.

或者最好的方法是切换到像hibernate这样的ORM工具,而不是将POJO对象直接映射到数据库的JDBC.

但截至目前使用此:

List<User> users=new ArrayList<User>();

while(rs.next()) {
   User user = new User();      
   user.setUserId(rs.getString("UserId"));
   user.setFName(rs.getString("FirstName"));
  ...
  ...
  ...


  users.add(user);
} 
Run Code Online (Sandbox Code Playgroud)

  • 如果结果集包含 300 个字段怎么办? (2认同)
  • 如果将来添加一些列怎么办?然后,这里也需要进行更改。 (2认同)

TEH*_*RAH 11

假设你想要使用核心Java,没有任何战略框架.如果可以保证,实体的字段名称将等于数据库中的列,则可以使用Reflection API(否则创建注释并在那里定义映射名称)

按FieldName

/**

Class<T> clazz - a list of object types you want to be fetched
ResultSet resultSet - pointer to your retrieved results 

*/

    List<Field> fields = Arrays.asList(clazz.getDeclaredFields());
    for(Field field: fields) {
        field.setAccessible(true);
    }

    List<T> list = new ArrayList<>(); 
    while(resultSet.next()) {

        T dto = clazz.getConstructor().newInstance();

        for(Field field: fields) {
            String name = field.getName();

            try{
                String value = resultSet.getString(name);
                field.set(dto, field.getType().getConstructor(String.class).newInstance(value));
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        list.add(dto);

    }
Run Code Online (Sandbox Code Playgroud)

通过注释

@Retention(RetentionPolicy.RUNTIME)
public @interface Col {

    String name();
}
Run Code Online (Sandbox Code Playgroud)

DTO:

class SomeClass {

   @Col(name = "column_in_db_name")
   private String columnInDbName;

   public SomeClass() {}

   // ..

}
Run Code Online (Sandbox Code Playgroud)

相同,但是

    while(resultSet.next()) {

        T dto = clazz.getConstructor().newInstance();

        for(Field field: fields) {
            Col col = field.getAnnotation(Col.class);
            if(col!=null) {
                String name = col.name();
                try{
                    String value = resultSet.getString(name);
                    field.set(dto, field.getType().getConstructor(String.class).newInstance(value));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        list.add(dto);

    }
Run Code Online (Sandbox Code Playgroud)

思考

事实上,迭代所有的字段可能看起来无效,所以我会将映射存储在某个地方,而不是每次都进行迭代.但是,如果我们T的DTO只是为了传输数据,并且不包含大量不必要的字段,那就没关系.最后,它比使用样板方法要好得多.

希望这有助于某人.