Java Spring JDBComany

Java Spring JDBComany,java,spring,spring-jdbc,jdbctemplate,Java,Spring,Spring Jdbc,Jdbctemplate,我收到以下错误,这表明我没有在结果集上调用next(),但我看到的是(即调试断点在rs.next()上停止并按预期填充) Servlet[dispatcherServlet]在具有路径的上下文中的Servlet.service() []引发异常[请求处理失败;嵌套异常为 org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback;SQL的未分类SQLException[选择 m、 用户名、m.pass

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

Servlet[dispatcherServlet]在具有路径的上下文中的Servlet.service() []引发异常[请求处理失败;嵌套异常为 org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback;SQL的未分类SQLException[选择 m、 用户名、m.password、t.name作为成员的权限m JOIN a.member\u id=m.member\u id加入管理员 t、 admin_type_id=a.admin_type_id,其中m.username=?];SQL状态 [24000];错误代码[0];结果集可能未正确定位 您需要调用next。;嵌套异常为 org.postgresql.util.PSQLException:结果集未正确定位, 也许你需要打电话给下一个。]根本原因

org.postgresql.util.PSQLException:结果集未正确定位, 也许你下次需要打电话

代码

SQL

结果

在您的代码中:

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()
不为真,也有可能是这样。但更重要的是,当您打破循环时,
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;
}
public User extractData(ResultSet rs)抛出SQLException、DataAccessException{
集合角色=新的ArrayList();
User=null;
while(rs.next()){
if(user==null){
用户=新用户(rs.getString(“用户名”)、rs.getString(“密码”)、角色);
}
字符串权限=rs.getString(“权限”);
添加(新的SimpleGrantedAuthority(authority));
}
if(user==null){
抛出新的MyException(“未找到用户”);
}
返回用户;
}

或者,对于这种样板代码,只需使用Hibernate之类的框架即可。

另一种方法是:

@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
   return ofNullable(userName)
            .map(u -> namedParameterJdbcTemplate.query(
                    "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",
                  Map.of("username", userName),
                  UserMapper.userWithRolesResultExtractor)
            )
            .orElseThrow(() -> new UsernameNotFoundException(
                format("Given username: %s does not exist in database", username)));
}
在另一个类中创建以下映射器(以重用它):

@UtilityClass
公共类用户映射器{
公共静态最终结果文本提取器userWithRolesResultExtractor=(结果集)->{
User=null;
while(resultSet.next()){
if(resultSet.isFirst()){
user=新用户(resultSet.getString(“用户名”),
resultSet.getString(“密码”)
新HashSet());
}
user.getRoles().add(新的SimpleGrantedAuthority(rs.getString(“authority”)));
}
返回用户;
};
}
正如Sebastiaan所提到的,有几种ORM可以帮助您编写更少的代码,但性能较差

警察局。在我的示例中,我使用了
Set
而不是
List
来避免重复

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;
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;
}
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
   return ofNullable(userName)
            .map(u -> namedParameterJdbcTemplate.query(
                    "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",
                  Map.of("username", userName),
                  UserMapper.userWithRolesResultExtractor)
            )
            .orElseThrow(() -> new UsernameNotFoundException(
                format("Given username: %s does not exist in database", username)));
}
@UtilityClass
public class UserMapper {
   public static final ResultSetExtractor<User> userWithRolesResultExtractor = (resultSet) -> {
      User user = null;
      while (resultSet.next()) {
        if (resultSet.isFirst()) {
            user = new User(resultSet.getString("username"),
                      resultSet.getString("password")
                      new HashSet<>());
        }
        user.getRoles().add(new SimpleGrantedAuthority(rs.getString("authority"))));
      }
      return user;
    };
}