我正在尝试为两个在它们之间具有@OneToMany关系的对象调整两个RowMappers。
假设我有两种方法:
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方法会抛出一个异常,说明“连接太多了!”。这是因为它们之间的行映射器的循环依赖性。我知道我这样做的方式不对,我想知道如何正确地重写行映射器。非常感谢。
答案 0 :(得分:1)
首先,你的java对象构造函数是&#34;递归&#34;紧密耦合。 Account
和Card
构造函数期望彼此作为参数。
你可以拥有一张没有卡的账户,对吧?因此,请删除帐户构造函数的卡片列表。
现在继续查询,加载帐户的卡片有两种情况:
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;
}
};