首页 > 解决方案 > 使用 JdbcTemplace.query() 时,每行结果都会执行一个 SELECT 查询

问题描述

我意识到,当我使用 JdbcTemplace.query() 执行一个返回许多记录的简单选择时,数百个选择正在后台执行。实际上每行一个,由于我的 ACL 表中某些用户的记录数量很多,这最终成为一个性能问题。


private final String PERMISSIONS_QUERY = "SELECT acl.user_id, acl.permission FROM v_user_acls acl WHERE acl.principal = :userId ";
private NamedParameterJdbcTemplate jdbcTemplate;

MapSqlParameterSource params = new MapSqlParameterSource(DAOConstants.USER_ID_KEY, userId);

List<UserPermissionRow> userPermissions = jdbcTemplate.query(PERMISSIONS_QUERY, params,
                new RowMapper<UserPermissionRow>() {
                    @Override
                    public UserPermissionRow mapRow(ResultSet rs, int rowNum) throws SQLException {
                        return new UserPermissionRow(rs.getString(1), rs.getString(2));
                    }
                });

我查看了显示正在执行的查询的 P6Spy 日志。如您所见,一个查询是按行执行的(我认为效率不是很高)。


READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10078, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10079, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10080, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10081, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10082, PERMISSION =
 READ
1566811816536|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10083, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10084, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10085, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10086, PERMISSION =
 READ
1566811816538|-1||resultset|SELECT acl.user_id, acl.permission FROM v_user_acls acl  WHERE acl.principal = '11582' |USER_ID = 10087, PERMISSION = READ

...
..
.

我想知道是否会有一种更有效的方法来检索如此大量的数据,只需一次选择到数据库。

我将非常感谢一些反馈。

问题中原始方法的响应时间为 5726 毫秒。

请参阅下面我尝试的替代方法。不幸的是,整体时间没有改善。

选项 1(状态)

Statement stmt = dataSource.getConnection().createStatement();
ResultSet rs = stmt.executeQuery(EXPERT_ACCESS_QUERY_2 + userId);
List<UserPermissionTest> list =new ArrayList<UserPermissionTest>();
    // ============= Expert Access Query RAW: 79 ms
while(rs.next()){
    UserPermissionTest e=new UserPermissionTest();
    e.setIdentity(rs.getString(1));
    e.setPermission(rs.getString(2));
    list.add(e);
}
    // ============ 5554 ms

选项 2(结果集提取器)

List <UserPermissionTest> userPerms = jdbcTemplate.query(EXPERT_ACCESS_QUERY_2 + userId, 
    new ResultSetExtractor<List<UserPermissionTest>>(){

    @Override
    public List<UserPermissionTest> extractData(ResultSet rs) throws SQLException, DataAccessException {

        List<UserPermissionTest> list =new ArrayList<UserPermissionTest>();
        while(rs.next()){
            UserPermissionTest e=new UserPermissionTest();
            e.setIdentity(rs.getString(1));
            e.setPermission(rs.getString(2));
            list.add(e);
         }
         return list;
    }
});
    //========= 5694 ms

标签: javadatabasejdbcoracle11gacl

解决方案


也许那是因为您在下面的 sql 脚本中使用了单个 userId:

private final String PERMISSIONS_QUERY = "SELECT acl.user_id, acl.permission FROM v_user_acls acl WHERE acl.principal = :userId ";

尝试使用 IN 并在 where 条件中使用 userID 列表作为参数?

如果这有帮助,我找到了这个参考: https ://www.technicalkeeda.com/spring-tutorials/spring-jdbctemplate-in-clause-example


推荐阅读