2014-11-05 70 views
1

我想適應兩個RowMappers的兩個對象,它們之間有@OneToMany關係。Spring RowMapper for OneToMany?

假設,我有兩種方法:

public Account findAccount(long id) { 
    SQL = "SELECT * FROM accounts WHERE id = ?"; 
    Account account = template.queryForObject(SQL, new Object[] { id }, MAP_ACCOUNT); 
    return account; 
} 


public Card findCard(String number) { 
    SQL = "SELECT * FROM cards WHERE number = ?"; 
    Card card = template.queryForObject(SQL, new Object[] { number }, MAP_CARD); 
    return card; 
} 

和兩個排映射器: 「太多的連接」

private final RowMapper<Card> MAP_CARD = new RowMapper<Card>() { 

    public Card mapRow(ResultSet rs, int rowNum) throws SQLException { 
     Account account = findAccount(rs.getLong("account_id")); 
     Card card = new DefaultCard(rs.getString("number"), account); 
     return card; 
    } 

}; 

private final RowMapper<Account> MAP_ACCOUNT = new RowMapper<Account>() { 

    public Account mapRow(ResultSet rs, int rowNum) throws SQLException { 
     SQL = "SELECT * FROM cards where account_id = " + rs.getLong("id"); 
     List<Card> cards = template.query(SQL, MAP_CARD); 
     Account account = new DefaultAccount(rs.getLong("id"), rs.getString("username"), cards); 
     return account; 
    } 
}; 

運行findAccount或findCard方法將拋出一個異常,說明。這是因爲它們之間的行映射器的循環依賴性。我知道我做了這個錯誤的方式,我想知道如何正確地重寫行映射器。非常感謝。

回答

1

首先你的java對象構造函數是「遞歸」緊密耦合的。 AccountCard構造函數期望彼此作爲參數。 你可以有一個沒有卡的帳戶,對吧?所以刪除Account構造函數的卡片列表。

現在移動到查詢,裝載帳戶卡時,有2種情況:

1 - 從賬戶加載卡:你已經有帳戶,也沒有必要查詢考慮每張卡片。所以你可以有一個MAP_CARD_FROM_ACCOUNT行映射器,通過參數接收帳戶。

2- 加載單卡:在這種情況下,你只需要在卡及其賬戶,所以對於MAP_CARD映射器你可以做一個查詢返回的卡和帳戶信息:SELECT * FROM cards C, accounts a WHERE c.account_id=a.id and number = ?

下面是映射程序代碼如何顯示的示例:

private final RowMapper<Card> MAP_CARD_FROM_ACCOUNT = new RowMapper<Card>() { 

    public void setAccount(Account account){ 
     this.account = account; 
    } 

    public Card mapRow(ResultSet rs, int rowNum) throws SQLException { 
     Card card = new DefaultCard(rs.getString("number"), account); 
     return card; 
    } 

}; 

private final RowMapper<Card> MAP_CARD = new RowMapper<Card>() { 

    public Card mapRow(ResultSet rs, int rowNum) throws SQLException { 
     Account account = new Account(rs.getLong("a.account_id"), rs.getString("a.username"); 
     Card card = new DefaultCard(rs.getString("c.number"), account); 
     return card; 
    } 

}; 

private final RowMapper<Account> MAP_ACCOUNT = new RowMapper<Account>() { 

    public Account mapRow(ResultSet rs, int rowNum) throws SQLException { 
     SQL = "SELECT * FROM cards where account_id = " + rs.getLong("id"); 
     Account account = new DefaultAccount(rs.getLong("id"), rs.getString("username")); 
     MAP_CARD_FROM_ACCOUNT.setAccount(account) 
     List<Card> cards = template.query(SQL, MAP_CARD_FROM_ACCOUNT); 
     account.setCards(cards); 
     return account; 
    } 
};