当前位置: 首页 > 知识库问答 >
问题:

将JDBC结果集映射到对象

魏雅惠
2023-03-14

我有一个用户类,有16个属性,比如名字,姓氏,出生日期,用户名,密码等...这些都存储在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);
} 

也就是说,我检索所有的列,然后通过将所有的列值插入用户构造函数来创建用户对象。

有人知道更快、更整洁的方法吗?

共有3个答案

屈健柏
2023-03-14

假设您希望使用核心Java,而不使用任何战略框架。如果您可以保证,实体的字段名将等于数据库中的列,则可以使用反射API(否则,在那里创建注释并定义映射名)

按字段名

/**

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);

    }

通过注释

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

    String name();
}

DTO:

class SomeClass {

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

   public SomeClass() {}

   // ..

}

一样,但是

    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);

    }

思想

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

希望这能帮助别人。

翟源
2023-03-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);
} 
石喜
2023-03-14

如果您不想使用任何JPA提供程序,如OpenJPA或Hibernate,您可以尝试使用ApacheDButils。

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);
 类似资料:
  • 我正在开发一个使用现有数据库的应用程序,该数据库只能通过存储过程访问。这些SP中的大多数返回来自多个表的列。 我们有一个数据访问层,它从我们的域对象层返回类型的对象。但是,由于SPs返回来自多个表的列,我不确定应该如何构建我的域对象,因为它们中的大多数不会“自然”映射到从SPs返回的数据。 示例:存储过程返回来自“员工”表和“经理”表的列: -员工ID -FirstName -LastName -

  • 问题内容: 我有一个具有16个属性的用户类,例如名,姓,dob,用户名,密码等。这些都存储在MySQL数据库中,当我要检索用户时,我使用ResultSet。我想将每个列映射回用户属性,但是我的操作方式似乎效率很低。例如我在做: 即我检索所有列,然后通过将所有列值插入到User构造函数中来创建用户对象。 有谁知道更快,更整洁的方法吗? 问题答案: 无需将resultSet值存储到String中,也无

  • null 没有将查询结果映射到域对象的基础结构。QueryDSL的QBean和MappingProject、Spring的BeanPropertyRowMapper和Spring-Data的OneToManyResultSetExtractor似乎级别太低,请参见下文。 没有在MyBatis中免费提供的现成会话/事务级缓存 Mybatis中没有免费提供的现成SQL语句和结果日志 因为我只问一个问题

  • 我开始使用JOOQ和dvd租赁商店数据库aka sakila。基本上,我想找一个演员和他的角色(我创建的表)。到目前为止,我想到了这个: 我希望能够将演员及其角色提取到一个对象中:DTO。我找到了这篇文章https://arnaudroger.github.io/blog/2017/03/02/jooq-one-to-many-without-dto.html但我发现使用sfm的解决方案过于冗长,

  • 我是Mapstruct的新手。我有一个Word对象,它包含一个字符串值和一组它自己,我想把它映射到WordDTO,它包含一个值和一组字符串值。我不知道怎么做。正如我在注释中所说,mapstruct不能映射两个对象是有道理的,但如果它有帮助,我将错误放在下面: 我为映射实现了这个接口: 谢谢你的帮助。

  • 在对这个话题进行了大量的测试和研究之后,我无法完全解决我的问题。我正在springboot应用程序中使用modelmapper进行实体/DTO映射。我正在尝试配置modelmapper,将一个集合映射到一个简单的DTO对象。我已经创建了一个自定义转换器,它正在按预期工作: 我现在的问题是将此转换器应用于所有“集合”= 如果我直接在模型映射器中添加转换器,它就是不工作。 你对此有什么提示或解决办法吗