如何使用DBUtils查询Set<MyObject>?ResultSetHandler实现类选型咨询
Set<MyObject> with Apache DBUtils Great question! Apache DBUtils doesn’t come with a built-in ResultSetHandler that directly returns a Set collection, but there are two straightforward, clean ways to make this work:
Option 1: Use BeanListHandler + Convert to Set
The quickest approach is to first fetch a List<MyObject> using the standard BeanListHandler, then convert it to a Set. This works flawlessly as long as your MyObject class properly implements equals() and hashCode()—this is non-negotiable for correct deduplication in the Set.
Here’s the code example:
QueryRunner queryRunner = new QueryRunner(yourDataSource); String sql = "SELECT * FROM your_table WHERE some_condition = ?"; // Fetch List<MyObject> first List<MyObject> objectList = queryRunner.query( sql, new BeanListHandler<>(MyObject.class), yourQueryParameters ); // Convert to Set (use TreeSet instead if you need sorted order) Set<MyObject> objectSet = new HashSet<>(objectList);
If you need a sorted Set, swap HashSet with TreeSet—just ensure MyObject implements Comparable, or pass a custom Comparator to the TreeSet constructor.
Option 2: Build a Reusable BeanSetHandler
If you find yourself needing a Set result often, create a custom ResultSetHandler that directly returns a Set. This cuts out the extra conversion step and keeps your code cleaner.
Here’s a basic, reusable implementation:
import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.RowProcessor; import org.apache.commons.dbutils.BasicRowProcessor; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; import java.util.Set; public class BeanSetHandler<T> implements ResultSetHandler<Set<T>> { private final Class<T> beanClass; private final RowProcessor rowProcessor; // Default constructor with standard row processing public BeanSetHandler(Class<T> beanClass) { this(beanClass, new BasicRowProcessor()); } // Constructor for custom row processing (advanced use cases) public BeanSetHandler(Class<T> beanClass, RowProcessor rowProcessor) { this.beanClass = beanClass; this.rowProcessor = rowProcessor; } @Override public Set<T> handle(ResultSet rs) throws SQLException { Set<T> beanSet = new HashSet<>(); while (rs.next()) { beanSet.add(rowProcessor.toBean(rs, beanClass)); } return beanSet; } }
Using this custom handler is just as simple as the built-in ones:
Set<MyObject> objectSet = queryRunner.query( sql, new BeanSetHandler<>(MyObject.class), yourQueryParameters );
Want a TreeSet instead? Just modify the handle() method to initialize beanSet as new TreeSet<>()—easy to adapt to your needs.
内容的提问来源于stack exchange,提问作者slvtn

