当前位置: 首页 > 知识库问答 >
问题:

Java Spring-行映射器结果集-整数值/空值

麹权
2023-03-14

我有一个JavaSE 8 Spring 4.1.6-RELEASE应用程序,我在其中实现了RowMapperorg.springframework.jdbc.core.

当我检查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);

等等,对于所有的原始类型?对于sqlnull的实例,其他一切都返回null

如果是这样,当类型化对象方法存在时,为不同类型提供所有方法有什么意义?

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

>

  • 使用getInt(字符串列标签)

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

    使用getObject(字符串列标签)并转换为整数

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

    使用getObject(String columnLabel,类类型)

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

    例如,我注意到了org。springframework。jdbc。果心JdbcTemplate过去有 queryForLong queryForInt 等方法,用于从单行查询中获取单个值,并将它们全部替换为类型化的 queryForObject方法。

    谢谢!


  • 共有2个答案

    柳鸿信
    2023-03-14
    • 使用resultSet。getXXX(String columnLabel)如果不允许使用SQL NULL,或者您只关心返回原语(无对象、盒装或数组类型)
    • 使用resultSet。getObject(String columnLabel,Class type)如果值可以是SQL NULL,但如果类型是装箱类型,则不要取消装箱,例如Integer,因为可以得到NullPointerException,因为原语不能是NULL
    • 使用resultSet。getObject(String columnLabel)如果运行Java 6,则使用强制转换

    如果列不允许SQL NULL,或者您的代码严格需要或需要一个基元,即没有对象类型(这包括装箱类型,例如Integer,实际上是对象的基元数组,例如byte[]),则使用特定的get方法:

    // Integer is 0 if value is SQL NULL
    int i = resultSet.getInt(column);
    
    // This is fine but Integer will never be null. This may or may not be what you want
    Integer j = resultSet.getInt(column);
    

    据我所知,这种方法的原因是方便,因为它可以优雅地处理SQL NULL,其中必须有一个基元,因为基元不能是NULL,例如int返回0。

    如果列确实允许sqlnull,或者代码需要对象类型(包括装箱类型或数组),则使用resultSet。getObject使用类型的类,但使用此方法时不要取消装箱类型的装箱:

    // Integer will be null on SQL NULL but that's OK for boxed types
    Integer i = resultSet.getObject(column, Integer.class);
    
    // Throws NullPointerException on SQL NULL since primitives can't be null
    int unbox = resultSet.getObject(column, Integer.class);
    
    // Integer will be 0 since getInt returns 0 on SQL NULL
    Integer autobox = resultSet.getInt(column);
    

    此方法还适用于受支持但没有特定get方法的其他SQL类型,即超出JDBC规范JSR-221中规定的最小值:

    // No getUUID method but it's supported by Postgres so no need for custom mapping
    UUID uuid = resultSet.getObject(column, UUID.class);
    

    但请注意,这个方法直到Java 7才被添加,所以如果您使用的是Java 6,则需要强制转换它:

    UUID uuid = (UUID) resultSet.getObject(column);
    

    因此,除非您真的不知道或不关心返回类型,否则没有理由使用它,除非您喜欢它的风格,或者您需要在Java 6上运行。

    最后,我的强烈建议是,在使用JDBC时,在使用(或取消装箱)装箱类型时要谨慎,以避免意外的NullPointerException。在模式中避免SQL NULL,例如,如果可以,默认为0;如果不能确定,则显式检查/转换。

    狄信然
    2023-03-14

    如果你看一下java.sql.ResultSet,你会发现你不需要如此明确。实际上,除非你有一个类型映射器为你的连接,允许你使用getObject方法,否则它将不起作用(java.sql.ResultSet.getObject)。

    我不知道这对你是否有帮助,但我设法找到了一个我自己的划船图,它非常适合我的需要。

    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() );
        }
    }
    

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

    只要数据库设置正确,并且使其在必填列上不为NULL,就永远不会遇到提取空行的问题。虽然我认为检查ResultSet中的空响应不会有什么坏处,但如果该列应该有值,那么最终还是会抛出异常。

     类似资料:
    • 我正在浏览Quarkus当前可用的指南 我说的是在不使用现有JPA实体的情况下,将SQL查询结果绑定到自定义pojo的可能性。我找到的所有示例都只从一个表中提取记录,从中提取出相同JPA实体的实例列表。然而,这不太可能是现实世界应用程序的常见用例。大多数情况下,我们必须处理不那么琐碎的查询,这些查询涉及来自不同表的字段的混合、连接或计算字段。 SQL ResultSet映射是一个方便的JPA功能,

    • Mapstruct在Spring-Boot rest api中使用一对多和多对一关系映射我的实体时遇到了一个问题。 我有下面的课 因此,当我在评论中添加私有UserDTO用户时;进入PolicyDTO和公共列表PolicyList;进入UserDTO 结果策略列出了所有字段中的值都可以,当然,除了两个注释字段。如果我用双向关系将这两个字段取消注释到DTO中,结果不仅在关系字段中是null,而且在所

    • 我使用了Oracle过程的out参数。out参数仅返回一个对象,该对象具有Oracle类型的嵌套对象。out pareemter应该是java bean TestEntity的精确映射,但mybatis说结果不包含TestEntity 请帮忙 Java bean: org.mybatis.spring.mybatisSystemException:嵌套异常为org.apache.ibatis.ex

    • 我试图使用JDK 8风格的函数按值对地图进行排序。虽然我得到了排序部分,但我不确定如何在树形图中收集结果。有人能解释一下如何以陈述式的方式完成这项工作吗? 我需要收集另一张

    • 我有一个用户类,有16个属性,比如名字,姓氏,出生日期,用户名,密码等...这些都存储在MySQL数据库中,当我想要检索用户时,我使用ResultSet。我想将每一列映射回用户属性,但我这样做的效率似乎非常低。例如,我正在做: 也就是说,我检索所有的列,然后通过将所有的列值插入用户构造函数来创建用户对象。 有人知道更快、更整洁的方法吗?