[英]Java SQL Many to Many relationship
我在 MySQL 中有一個名為 Orders 的表,其中包含訂單的詳細信息。 我有另一個名為 OrderItems 的表。
OrderItems 包含以下字段:OrderID、ProductID、Qty
現在在 Java 中,我有一個名為 Order 的類,它有一個列表。
假設我想從我的數據庫中獲取所有訂單,包括每個訂單的訂單項。 但我想以最有效的方式做到這一點。
我目前的解決方案(我認為可能很慢)是:
循環遍歷行的 ResultSet 並定義 OrderDetails,每次循環遍歷一行時,我都會執行另一個 PreparedStatement 並使用當前訂單的 OrderID 循環遍歷 OrderItems。 然后我在列表中添加項目並轉到下一個訂單。
但我可以想象,這個過程會極其緩慢且資源密集。 什么是最有效的方法來做到這一點,同時仍然被歸一化(3NF)。
根據要求,我寫了一個解決方案的例子
public List<Order> getAllOrders() throws SQLException{
ArrayList<Order> list = new ArrayList<Order>(0);
ResultSet x = qry("Select * from Orders");
while(x.next()){
Order r = new Order();
//setOrderDetails
r.setItems(getOrderItems(r));
}
return list;
}
public ArrayList<OrderItem> getOrderItems(Order r) throws SQLException {
ArrayList<OrderItem> list = new ArrayList<OrderItem>(0);
ResultSet x = qry("Select * from OrderItems where OrderID = "+r.getId()+";");
while(x.next()){
OrderItem newItem = new OrderItem();
newItem.setOrderId(r.getId());
newItem.setProduct(null); //Uses some kind of inner join to get the product details
newItem.setPrice(newItem.getProduct().getPrice());
newItem.setQuantity(x.getInt(4));
}
return list;
}
好的,我已經按照你們的建議做了……平均仍然需要 20 多秒看起來如何
日志:
Time took to connect: 3270ms
Start CustomerService: 38ms
Start ProductService: 1ms
Start OrderService: 2ms
Customer Size: 4
Qry All Customers: 149ms
Products Size: 420
Qry All Products: 391ms
Order already contains: ENALAPRILMALEAAT HCT 20/12,5MG ACTAVIS BV
Add Order(28 items) Took: 2350ms
Qry all orders(27 orders) took: 7929ms
這真的很難......有時可能需要長達 20 秒。(查詢所有訂單)
這是另一個仍在計時 30 秒的訂單,僅可查詢 28 個訂單..(每個訂單最多 28 個項目
Time took to connect: 7117ms Start CustomerService: 35ms Start ProductService: 1ms Start OrderService: 1ms Customer Size: 4 Qry All Customers: 126ms Products Size: 420 Qry All Products: 700ms Add Order(6 items) Took: 2117ms Qry all orders(28 orders) took: 30150ms
在我看來,您的數據(每周 4 個新訂單的 600 種產品)並不大,您現在應該需要進行性能優化。 但是如果你應該,你可以優化它,如果你的代碼看起來像下面這樣(我只是稍微修改了你的代碼):
public List<Order> getAllOrders() throws SQLException{
ArrayList<Order> list = new ArrayList<Order>(0);
PreparedStatement ps = connection.prepareStatement("Select * from OrderItems where OrderID = ?"); // (1)
ResultSet x = qry("Select * from Orders");
while(x.next()){
Order r = new Order();
//setOrderDetails
r.setItems(getOrderItems(r, ps));
list.add(r);
}
return list;
}
public ArrayList<OrderItem> getOrderItems(Order r, PreparedStatement ps) throws SQLException {
ArrayList<OrderItem> list = new ArrayList<OrderItem>(0);
ps.setString(1, r.getId()); // (2)
ResultSet x = ps.executeQuery(); // (3)
while(x.next()){
OrderItem newItem = new OrderItem();
newItem.setOrderId(r.getId());
newItem.setProduct(null); //Uses some kind of inner join to get the product details
newItem.setPrice(newItem.getProduct().getPrice());
newItem.setQuantity(x.getInt(4));
}
return list;
}
現在發生了什么變化?
准備好的語句現在已退出循環,它將被重用(請參閱更改 (1))。 與之前准備好的查詢相比,這應該會帶來巨大的性能提升,因為查詢只會被解析一次。
在 (2) 中,將為當前訂單設置參數。
在 (3) 中,將執行查詢。
這是一個遲到的答案,但對於那些查詢時間很慢的人來說。 嘗試將自動提交設置為 false。 在代碼中實際創建連接時,執行 connection.setAutoCommit(false); 然后在代碼中放入 connection.commit(); 執行查詢后。 我在嘗試插入 150000 個對象時遇到了同樣的問題,這需要大約 23 分鍾。 將自動提交設置為 false 然后提交后,我花了大約 27 秒。 我希望它有幫助。
這是提交的代碼示例:
@Override
public void create(Member member) {
try {
Connection connection = localConnection.getConnection();
PreparedStatement sqlInsert = connection.prepareStatement(memberDaoUtil.create());
sqlInsert.setString(1, member.getMemberId());
sqlInsert.setString(2, member.getName());
sqlInsert.setString(3, member.getPersonalNumber());
sqlInsert.setString(4, member.getUsername());
sqlInsert.setString(5, member.getPassword());
sqlInsert.setInt(6, member.getNumOfBoats());
sqlInsert.setBoolean(7, member.isAdmin());
sqlInsert.executeUpdate();
connection.commit();
sqlInsert.close();
} catch(SQLException ex) {
ex.printStackTrace();
}
}
然后也在連接的構造函數中:
private LocalConnection(Connection connection) {
this.connection = connection;
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
你可以看到 connection.setAutoCommit(false); 您可以在下面的鏈接中閱讀它的作用。 了解自動提交
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.