我有一个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
方法。
谢谢!
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;如果不能确定,则显式检查/转换。
如果你看一下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。我想将每一列映射回用户属性,但我这样做的效率似乎非常低。例如,我正在做: 也就是说,我检索所有的列,然后通过将所有的列值插入用户构造函数来创建用户对象。 有人知道更快、更整洁的方法吗?