2012-03-03 10 views
2

新しいプロジェクトでは、永続ドメインオブジェクトにSpring MVCとJdbcTemplate(特にSimpleJdbcTemplate)を使用することに決めました。このアプローチで私が抱えていた1つの問題は、SELECTクエリからオブジェクトグラフをきれいに作成する方法です。 RowMapperのメカニズムは、単一のテーブルから行を引っ張っているときにうまくいくと思われます。私は、JOINクエリの結果をマッピングしているときに気になる。SimpleJdbcTemplateを使用してドメインオブジェクトのオブジェクトグラフをきれいに作成

コンクリートを与える(まだ完全に製造された)、実施例、私はN対1の関係にある2つのエンティティがあるとします。私は私のInvoiceDAOselectInvoices()メソッドを呼び出すことができるようにしたいと思い

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

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

を完全に形成されたCustomerインスタンスが入力されたInvoiceのリストを取得します。代わりに、私は自分自身には、次のような何かを誘惑見つける:

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

きれいにこれを実現させるためのベストプラクティスは何ですか?私は弾丸を噛んでORMを使うべきですか?

+0

良い質問、そしてあなたのDAOのか、POJOのを濁っしたくない場合、あなたは行く必要があります:あなたは自分でそれをすべて行いたい場合は、私のトリックは、顧客を保持するためにマップを使用することですORMルート。 – Perception

答えて

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に保持されたままです。パフォーマンスを失うのは残念ですが、DBに結合を指示するACIDプロパティもあります。それが妥協の本質ですよね? – nstory

+0

上記のコードのアイデアは、i.customer_id = cの 'select i。*、c。* from invoice i inner join customer c 'のような結合クエリから来る単一の結果セットから顧客との請求書を正確に読み込むことです。どこに...ここにN + 1の問題はありません。 –

+0

ああ!あなたの答えは間違っています。あなたはそうです:そこにN + 1の問題はありません。 – nstory

関連する問題