Java Spring - RowMapper ResultSet - 整数/空值

ano*_*ous 9 java spring jdbc jdbctemplate

我有一个Java SE 8 Spring 4.1.6-RELEASE应用程序,我正在实现该org.springframework.jdbc.core.RowMapper<T>接口,我java.sql.ResultSet对其T mapRow(ResultSet rs, int rowNum)方法中传递的接口有一些疑问.

当我检查ResultSet类时,我看到了一堆方法来获取列值:

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? Return Type  ?       Method        ?                                                                   Return (javadoc, se 8)                                                                   ?
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? String       ? getString           ? the column value; if the value is SQL NULL, the value returned is null                                                                                     ?
? boolean      ? getBoolean          ? the column value; if the value is SQL NULL, the value returned is false                                                                                    ?
? byte         ? getByte             ? the column value; if the value is SQL NULL, the value returned is 0                                                                                        ?
? short        ? getShort            ? the column value; if the value is SQL NULL, the value returned is 0                                                                                        ?
? int          ? getInt              ? the column value; if the value is SQL NULL, the value returned is 0                                                                                        ?
? long         ? getLong             ? the column value; if the value is SQL NULL, the value returned is 0                                                                                        ?
? float        ? getFloat            ? the column value; if the value is SQL NULL, the value returned is 0                                                                                        ?
? double       ? getDouble           ? the column value; if the value is SQL NULL, the value returned is 0                                                                                        ?
? BigDecimal   ? getBigDecimal       ? the column value; if the value is SQL NULL, the value returned is null                                                                                     ?
? byte[]       ? getBytes            ? the column value; if the value is SQL NULL, the value returned is null                                                                                     ?
? Date         ? getDate             ? the column value; if the value is SQL NULL, the value returned is null                                                                                     ?
? Time         ? getTime             ? the column value; if the value is SQL NULL, the value returned is null                                                                                     ?
? Timestamp    ? getTimestamp        ? the column value; if the value is SQL NULL, the value returned is null                                                                                     ?
? InputStream  ? getAsciiStream      ? a Java input stream that delivers the database column value as a stream of one-byte ASCII characters; if the value is SQL NULL, the value returned is null ?
? Reader       ? getCharacterStream  ? a java.io.Reader object that contains the column value; if the value is SQL NULL, the value returned is null in the Java programming language              ?
? InputStream  ? getBinaryStream     ? a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the value is SQL NULL, the value returned is null       ?
? <T> T        ? getObject           ? an instance of type holding the column value                                                                                                               ?
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

通常的期望/做法是:

rs.getObject("COLUMN_NAME", Boolean.class);

rs.getObject("COLUMN_NAME", Byte.class);

rs.getObject("COLUMN_NAME", Short.class);

rs.getObject("COLUMN_NAME", Integer.class);

rs.getObject("COLUMN_NAME", Long.class);
Run Code Online (Sandbox Code Playgroud)

等,对于所有原始类型?正如其他所有东西返回null的实例一样SQL NULL.

如果是这样,当有类型的Object方法存在时,为不同类型设置所有方法的重点是什么?

另外,每种方法的优缺点是什么?

  1. 使用getInt(String columnLabel):

    Integer resultingActionId = rs.getInt("RESULTING_ACTION_ID");
    if (rs.wasNull) {
        resultingActionId = null
    }

  2. 使用getObject(String columnLabel)和转换为Integer:

    Integer resultingActionId = (Integer) rs.getObject("RESULTING_ACTION_ID");

  3. 使用getObject(String columnLabel, Class type):

    Integer resultingActionId = rs.getObject("RESULTING_ACTION_ID", Integer.class);

举例来说,我发现org.springframework.jdbc.core.JdbcTemplate以前有queryForLong,queryForInt用于从单行查询得到一个单值等方法,取而代之他们都赞成类型化的queryForObject方法.

谢谢!

aai*_*zza 3

如果你看一下java.sql.ResultSet,你会发现你不需要那么明确。实际上,除非您有一个允许您使用 getObject 方法的连接的 typeMapper,否则它将无法工作(java.sql.ResultSet.getObject)。

我不知道它是否对您有帮助,但我设法找到了自己的 RowMapper,它非常适合我的需求。

private class ShabaUserMapper implements RowMapper<ShabaUser>
{
    @Override
    public ShabaUser mapRow( ResultSet rs, int rowNum ) throws SQLException
    {
        Collection<SimpleGrantedAuthority> roles = new ArrayList<SimpleGrantedAuthority>();

        String auths = rs.getString( "role" );

        roles.add( new SimpleGrantedAuthority( auths ) );

        ShabaUser user = new ShabaUser( rs.getString( "username" ), rs.getString( "password" ),
                rs.getBoolean( "enabled" ), rs.getString( "first_name" ),
                rs.getString( "last_name" ), rs.getString( "email" ),
                rs.getString( "date_joined" ), rs.getString( "last_online" ), true, true, true,
                roles );

        // Can be null!
        Integer awesomeness = rs.getInt( "awesomeness" );
        if ( rs.wasNull() )
        {
            awesomeness = null;
        }

        user.setAwesomeness( awesomeness );

        return user;
    }
}

private class ShabaUserListExtractor implements ResultSetExtractor<List<ShabaUser>>
{
    private final ShabaUserMapper rowMapper;

    private int                   rowsExpected;

    public ShabaUserListExtractor()
    {
        this( new ShabaUserMapper(), 0 );
    }

    public ShabaUserListExtractor( ShabaUserMapper rowMapper, int rowsExpected )
    {
        Assert.notNull( rowMapper, "RowMapper is required" );
        this.rowMapper = rowMapper;
        this.rowsExpected = rowsExpected;
    }

    @Override
    public List<ShabaUser> extractData( ResultSet rs ) throws SQLException
    {
        HashMap<String, ShabaUser> results = ( this.rowsExpected > 0
                                                                    ? new HashMap<String, ShabaUser>(
                                                                            rowsExpected )
                                                                    : new HashMap<String, ShabaUser>() );
        int rowNum = 0;
        while ( rs.next() )
        {
            ShabaUser user = rowMapper.mapRow( rs, rowNum++ );

            if ( results.containsKey( user.getUsername() ) )
            {
                ShabaUser inUser = results.get( user.getUsername() );
                ArrayList<GrantedAuthority> combinedAuthorities = new ArrayList<GrantedAuthority>();

                combinedAuthorities.addAll( inUser.getAuthorities() );
                combinedAuthorities.addAll( user.getAuthorities() );

                results.put( user.getUsername(),
                    createUserDetails( user.getUsername(), user, combinedAuthorities ) );
            } else
            {
                results.put( user.getUsername(), user );
            }
        }

        return new ArrayList<ShabaUser>( results.values() );
    }
}
Run Code Online (Sandbox Code Playgroud)

我意识到这是很多代码,但希望您能看到这里完成了什么。实际的 RowMapper 实现实际上是为了容纳从行信息中提取对象的所有“脏工作”。

只要您的数据库设置正确并且在必需的列上设置了 NOT NULL,您就永远不会遇到拉出空行的问题。虽然我认为检查 ResultSet 中的空响应不会有什么坏处,但如果该列应该有一个值,您仍然最终会抛出异常。