3つのテーブルを結合するSQLクエリがあり、1つは他の2つを接続する多対多です。Spring JDBC ResultSetExtractorを使用して、ResultSetを次のようなオブジェクトに変換します。
class Customer {
private String id;
private Set<AccountType> accountTypes;
...
}
ResultSetExtractorの実装は次のようになります。
public List<Client> extractData(ResultSet rs) throws SQLException,
DataAccessException {
Map<Integer, Client> clientsMap = new LinkedHashMap<Integer, Client>();
while (rs.next()) {
int id = rs.getInt("id");
// add the client to the map only the first time
if (!clientsMap.containsKey(id)) {
Client client = new Client();
client.setId(id);
...
clientsMap.put(id, client);
}
// always add the account type to the existing client
Client client = clientsMap.get(id);
client.addAccountType(extractAccountTypeFrom(rs, id));
}
return new ArrayList<Client>(clientsMap.values());
}
これは、ページネーションなしで正常に機能します。
ただし、これらの結果をページ分割する必要があります。私が通常行う方法は、これをクエリに追加することです。次に例を示します。
SELECT ... ORDER BY name ASC LIMIT 10 OFFSET 30;
ただし、このクエリには結合があるため、結果の数を制限すると、実際にはJOINEDの結果の数が制限されます(つまり、クライアントはアカウントタイプの数と同じ回数表示されるため、LIMITは適用されません。クライアントの数ですが、clients * accountTypesの数になりますが、これは私が望むものではありません)。
私が思いついた唯一の解決策は、クエリからLIMIT(およびそれも間違っているためOFFSET)を削除し、プログラムで適用することでした。
List<Client> allClients = jdbcTemplate.query....
List<Client> result = allClients.subList(offset, offset+limit);
しかし、これは明らかに非常に優れた効率的なソリューションではありません。もっと良い方法はありますか?