Có thực sự không có cách nào đơn giản để làm điều này trong JDBC. Một số Trình điều khiển JDBC dường như hỗ trợ PreparedStatement#setArray()
theo mệnh đề IN
. Tôi chỉ không chắc đó là cái nào.
Bạn chỉ có thể sử dụng phương thức trợ giúp với String#join()
và Collections#nCopies()
để tạo trình giữ chỗ cho mệnh đề IN
và một phương thức trợ giúp khác để đặt tất cả các giá trị trong vòng lặp với PreparedStatement#setObject()
.
public static String preparePlaceHolders(int length) {
return String.join(",", Collections.nCopies(length, "?"));
}
public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i + 1, values[i]);
}
}
Đây là cách bạn có thể sử dụng nó:
private static final String SQL_FIND = "SELECT id, name, value FROM entity WHERE id IN (%s)";
public List<Entity> find(Set<Long> ids) throws SQLException {
List<Entity> entities = new ArrayList<Entity>();
String sql = String.format(SQL_FIND, preparePlaceHolders(ids.size()));
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(sql);
) {
setValues(statement, ids.toArray());
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
entities.add(map(resultSet));
}
}
}
return entities;
}
private static Entity map(ResultSet resultSet) throws SQLException {
Enitity entity = new Entity();
entity.setId(resultSet.getLong("id"));
entity.setName(resultSet.getString("name"));
entity.setValue(resultSet.getInt("value"));
return entity;
}
Lưu ý rằng một số cơ sở dữ liệu có một giới hạn của khoản chấp nhận các giá trị trong mệnh đề IN
. Ví dụ, Oracle có giới hạn trên 1000 mục.
Đó là những gì chúng tôi đang làm ngay bây giờ, nhưng những gì tôi đã hy vọng rằng có một cách thống nhất để làm điều đó mà không cần SQL tùy chỉnh ... – Uri
Ngoài ra, nếu nó giống như Oracle, nó sẽ phải reparse nhất mọi tuyên bố. – orbfish