java - Spring jdbcTemplate OneToMany

标签 java spring spring-jdbc jdbctemplate

我收到以下错误,这表明我没有在结果集上调用 next(),但据我所知(即调试断点停止在 >rs.next() 并按预期填充)。

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT m.username, m.password, t.name as authority FROM members m JOIN administrator a ON a.member_id = m.member_id JOIN admin_type t ON t.admin_type_id = a.admin_type_id WHERE m.username = ?]; SQL state [24000]; error code [0]; ResultSet not positioned properly, perhaps you need to call next.; nested exception is org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next.] with root cause

org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next.

代码

    @Autowired
    NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        String sql = "SELECT m.username, m.password, t.name as authority FROM members m " +
                "JOIN administrator a ON a.member_id = m.member_id " +
                "JOIN admin_type t ON t.admin_type_id = a.admin_type_id " +
                "WHERE m.username = :userName";
        SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("userName", userName);
        List<User> users = namedParameterJdbcTemplate.query(sql, namedParameters, new UserDetailsRowMapper());
        return users.get(0);
    }

    class UserDetailsRowMapper implements RowMapper<User> {
        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            UserResultSetExtractor extractor = new UserResultSetExtractor();
            return extractor.extractData(rs);
        }
    }

    class UserResultSetExtractor implements ResultSetExtractor {
        public User extractData(ResultSet rs) throws SQLException, DataAccessException {
            Collection<SimpleGrantedAuthority> roles = new ArrayList<>();
            while (rs.next()) {
                String authority = rs.getString("authority");
                roles.add( new SimpleGrantedAuthority(authority));
            }
            User user = new User(rs.getString("username"), rs.getString("password"), roles);
            return user;
        }
    }

我不确定为什么会收到此错误。这可能是因为我的逻辑不正确,因为为结果集中的每一行调用了 extractData()

问题

我应该如何执行上述操作来填充与authorities具有一对多关系的User对象?

 +-----------+     +---------------+     +---------------+
 | Member    |     | administrator |     |  admin_type   |
 +-----------+     +---------------+     +---------------+
 | member_id |     | admin_id      |     | admin_type_id |
 | username  |     | member_id     |     |   name        |
 | password  |     | admin_type_id |     +---------------+ 
 +-----------+     +---------------+

SQL

SELECT m.username, m.password, t.name as authority FROM members m 
JOIN administrator a ON a.member_id = m.member_id 
JOIN admin_type t ON t.admin_type_id = a.admin_type_id 
WHERE m.username = 'richardmarais';

结果

最佳答案

在您的代码中:

while (rs.next()) {
    String authority = rs.getString("authority");
    roles.add( new SimpleGrantedAuthority(authority));
}
User user = new User(rs.getString("username"), rs.getString("password"), roles);
return user;

您在 while 循环之外调用 rs.getString,因此即使 rs.next() 没有为 true,也有可能。但更重要的是,当您跳出循环时,rs.next() 已返回 false,因此您的 get 将不再起作用。您没有提到在哪一行抛出异常,但我认为这是最可能的原因。

您应该在获取权限时随时填充用户信息,例如在第一行。但不要等到您已经处理完所有行。

例如这样:

public User extractData(ResultSet rs) throws SQLException, DataAccessException {
    Collection<SimpleGrantedAuthority> roles = new ArrayList<>();
    User user = null;
    while (rs.next()) {
        if (user == null) {
            user = new User(rs.getString("username"), rs.getString("password"), roles);
        }
        String authority = rs.getString("authority");
        roles.add( new SimpleGrantedAuthority(authority));
    }
    if (user == null) {
        throw new MyException("User not found");
    }
    return user;
}

或者,只需使用 Hibernate 之类的框架来编写此类样板代码。

关于java - Spring jdbcTemplate OneToMany,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62523016/

相关文章:

java - JDialog/OptionPane 带有带图标的大自定义按钮

java - Spring异步执行器: remove from queue after x time

java - Spring Initializr 为 tomcat 创建 WAR?

java - 构建在 Spring 3 (m3) 上的 REST-fully 注释服务的最小配置是什么?

java - 如何模拟在构造函数中创建的类?

java - 如何从Spring Jdbc中的存储过程读取返回值(过程中没有输出参数)

java - 我可以将 jaxb 与 hibernate hbm2ddl 一起使用吗?

java - 如何获取 XSOM Java 库中的 Use Attribute

java - spring上传文件大小限制报错

java - Spring JDBCTemplate Mysql 从 Mysql 驱动程序抛出 ArrayIndxOutofBound