#java #resultset
#java #результирующий набор
Вопрос:
У меня есть код для сбора некоторых данных из базы данных в результирующий набор (данные продуктов). Моя модель продукта выглядит следующим образом:
public class Product {
private Integer avail;
private Long id;
private BigDecimal price;
private String url;
private Integer stock;
private String category;
private String title;
private String description;
private List<String> attribute;
private Map<String, String> attributes;
//getters-setters-toString
Другой класс — собирать продукты в список:
public class Products {
private List<Product> products = null;
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}
Результат моего запроса к базе данных выглядит следующим образом:
=============================================================
products_id||attribute key||attribute valu||some other data ...
=============================================================
1 a1:k1 a1:v some other data ...
1 a1:k2 a1:v some other data ...
1 a1:k3 a1:v some other data ...
1 a1:k4 a1:v some other data ...
1 a1:k5 a1:v some other data ...
2 a2:k1 a2:v some other data ...
2 a2:k2 a2:v some other data ...
2 a2:k3 a2:v some other data ...
2 a2:k4 a2:v some other data ...
3 a3:k1 a3:v some other data ...
4 a4:k1 a4:v some other data ...
5 a5:k1 a5:v some other data ...
5 a5:k2 a5:v some other data ...
5 a5:k3 a5:v some other data ...
=============================================================
Мне нужно создать List<Product>
вот так:
=================================================
products_id | attributes | some other data ...
=================================================
1 k1:v, k2:v... some other data ...
2 k1:v, k2:v... some other data ...
3 k1:v some other data ...
4 k1:v some other data ...
5 k1:v, k2:v... some other data ...
=================================================
Выберите запрос:
String query = "SELECTn"
"p.products_id, n"
"p.products_price_tax, n"
"p.products_availability_id, n"
"p.products_quantity, n"
"p.products_image, n"
"cd.categories_name, n"
"pd.products_name, n"
"pd.products_description, n"
"pef.products_extra_fields_name,n"
"ptpef.products_extra_fields_valuen"
"FROM n"
"products p n"
"LEFT JOIN n"
"products_to_categories ptc n"
"ON n"
"ptc.products_id = p.products_id n"
"LEFT JOIN n"
"categories_description cd n"
"ON n"
"cd.categories_id = ptc.categories_id n"
"LEFT JOIN n"
"categories c n"
"ON n"
"c.categories_id = cd.categories_id n"
"LEFT JOIN n"
"products_description pd n"
"ON n"
"pd.products_id = p.products_id n"
"LEFT JOINn"
"products_to_products_extra_fields ptpefn"
"ONn"
"ptpef.products_id = p.products_idn"
"LEFT JOINn"
"products_extra_fields pefn"
"ONn"
"pef.products_extra_fields_id = ptpef.products_extra_fields_idn"
"WHERE n"
"p.products_status = 1n"
"ANDn"
"c.categories_id IN (83, 104, 102, 106, 92)";
Я пытался создать что-то вроде этого:
conn = DriverManager.getConnection("connection data");
selectProducts = conn.prepareCall(query);
rs = selectProducts.executeQuery();
while (rs.next()) {
String tmpId = rs.getString("products_id");
attr = new ArrayList<>();
Product product = new Product();
product.setId(rs.getLong("products_id"));
product.setPrice(rs.getBigDecimal("products_price_tax"));
product.setAvail(rs.getInt("products_availability_id"));
product.setStock(rs.getInt("products_quantity"));
product.setCategory(rs.getString("categories_name"));
product.setTitle(rs.getString("products_name"));
product.setDescription("products_description");
attr.add(rs.getString("products_extra_fields_name"));
attr.add( rs.getString("products_extra_fields_value"));
product.setAttribute(attr);
mainList.add(product);
}
// mainList.forEach(product -> System.out.println(product));
Product tmpProduct = null;
List<Product> tmpProductList = new ArrayList<>();
Map<String, String> tmpAttr = new HashMap<>();
for (int i = 0; i < mainList.size() - 1; i ) {
if (mainList.get(i).getId().equals(mainList.get(i 1).getId())) {
tmpAttr.put(mainList.get(i).getAttribute().get(1),mainList.get(i).getAttribute().get(2)); //here I am getting NullPointerException
} else {
tmpAttr.put(mainList.get(i).getAttribute().get(0),mainList.get(i).getAttribute().get(1));
tmpProduct = mainList.get(i);
tmpProduct.setAttributes(tmpAttr);
tmpProductList.add(tmpProduct);
tmpAttr = null;
tmpProduct = null;
}
}
Поэтому я пытался создать что-то новое List<Product>
и работать с этим. Есть ли какой-нибудь более простой способ решить эту задачу?
Комментарии:
1. Вы думали об ORM API?
2. Пропущенный «код подключения» очень важен, потому что, основываясь на том, как вы извлекаете свои данные, вы можете, например, передавать их непосредственно в
List<Product>
то, что вам нужно. Детали зависят от размера набора данных, но общая идея заключалась бы в том, чтобы передавать его в списокProduct
напрямую.3. @TreffnonX Я думаю, что через некоторое время я перепишу код в режиме гибернации, но сейчас я хочу найти решение для этой задачи
4. @Dropout Я добавлю удаленные данные через секунду
Ответ №1:
Вы можете использовать библиотеку jOOQ для создания потока, который просто отображается в список
Connection conn = DriverManager.getConnection("connection data");
PreparedStatement pSt = connection.prepareStatement(query); //your SQL query
ResultSet rs = pSt.executeQuery();
List<Product> productList;
try(Stream<Record> productStream = DSL.using(conn).fetchStream(rs)){ //jOOQ DSL
productList = productStream
.map(p -> {
Product product = new Product();
//casting after get might be necessary
product.setAvail(p.get("products_availability_id"));
//do the same for other fields you'd like to map to Product
return product;
})
.collect(Collectors.toList());
}
Комментарии:
1. Пожалуйста, обратите внимание, что это не решение для копирования и вставки, а скорее общая идея подхода. Я пишу код из головы, не тестируя на данный момент.