2014-11-05 71 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; 
    } 
};