2012-03-03 44 views
2

對於新項目,我們決定使用Spring MVC和JdbcTemplate(特別是SimpleJdbcTemplate)來保存域對象。我一直在用這種方法處理的一個問題是如何從SELECT查詢中乾淨地創建對象圖。當我從單個表中拉行時,RowMapper機制似乎很好用;當我映射JOIN查詢的結果時,我很擔心。使用SimpleJdbcTemplate乾淨地創建域對象的對象圖

舉一個具體的(尚未完全製造)例如,假設我有在N對1的關係兩個實體:

public class Invoice { 
    private Customer customer; 
    ... 
} 

public class Customer { 
    private int id; 
    private String name; 
    ... 
} 

我想能夠調用一個selectInvoices()方法在我InvoiceDAO ,並檢索一個列表Invoice填充完整形式的Customer實例。相反,我發現自己想做類似下面的事情:

public class Invoice { 
    // this makes me unhappy 
    private int customerId; 
    ... 
} 

乾淨地做到這一點的最佳做法是什麼?我應該咬一口子彈並使用ORM嗎?

+0

好問題,如果你不想攪渾你的DAO的或POJO的,那麼你將不得不去ORM路線。 – Perception 2012-03-03 17:45:38

回答

2

這正是ORM擅長的。如果你想全部由自己來做,我的訣竅是使用地圖來保存客戶:

Map<Long, Customer> customersById = new HashMap<Long, Customer>(); 
... 
public Invoice mapRow(ResultSet rs, int rowNum) throws SQLException { 
    Invoice invoice = ... 
    // populate invoice fields 
    Long customerId = rs.getLong("customerId"); 
    Customer c = customersById.get(customerId); 
    if (c == null) { 
     // first time we meet this customer 
     c = ... 
     // populate customer fields from result set 
     customersById.put(customerId, c); 
    } 
    invoice.setCustomer(c); 
} 
+0

我看到這是如何緩解(但並未消除)N + 1 SQL反模式。如果我知道我的「客戶」數量很少(或者給定典型輸入重複),這似乎是一個很好的解決方案。它不會在我的RowMapper中過多地瞭解客戶表;知識保留在CustomerDAO中。感覺像是失去了指示數據庫進行連接的性能和ACID屬性的恥辱。這就是妥協的性質,對吧? – nstory 2012-03-03 21:03:55

+0

上述代碼的想法正是從一個結果集加載發票給他們的客戶,來自一個連接查詢,例如'select i。*,c。* from invoice i inner join customer c on i.customer_id = c。 id在哪裏......'。我在這裏看不到任何N + 1問題。 – 2012-03-03 21:07:59

+0

哦!我讀錯了你的答案。你是對的:那裏沒有N + 1個問題。 – nstory 2012-03-03 21:15:00