javasetnull值,从JavaResultSet检查nullint值
在Java中,我试图从ResultSet中测试是否为空值,在ResultSet中,该列将被强制转换为原始int类型。
int iVal;
ResultSet rs = uteQuery(query);
if (rs.next()) {
if (rs.getObject("ID_PARENT") != null && !rs.wasNull()) {
iVal = rs.getInt("ID_PARENT");
}
}
从上⾯的代码⽚段中,是否有更好的⽅法可以做到这⼀点,并且我认为第⼆个wasNull()测试是多余的?
教育我们,谢谢
我发现了这个问题,因为我在数据库中有⼀个可为空的列,⽽该列由Java中的Integer表⽰。 您会认为,在数据库中具有可为空的数字列已⾜够普遍,以致ResultSet API会更优雅地容纳它。
当字段值是NULL时,Int的默认值是返回0,这也是iVal声明的默认值。在这种情况下,您的测试是完全多余的。
如果您实际上想在字段值为NULL的情况下执⾏其他操作,则建议:
int iVal = 0;
ResultSet rs = uteQuery(query);
if (rs.next()) {
iVal = rs.getInt("ID_PARENT");
if (rs.wasNull()) {
// handle NULL field value
}
}
(在下⾯编辑为@martin注释;由于未初始化iVal,因此所编写的OP代码将⽆法编译)
⾹港专业教育学院刚刚在⽂档中到相同的声明。值得在SO imho上另辟thread径。 (java.sun/j2se/1.4.2/docs/api/java/sql/)
@Roman-请参见ResultSet中的getInt的javadoc:"返回:列值;如果该值为SQL NULL,则返回的值为0"
罗马,真是荒谬! :)
事实的确是荒谬的。 getInt()应该是getInteger(),如果DB值为null,则返回null的Integer。开发⼈员真的搞砸了这⼀件事。
仅作记录:我不认为iVal的默认值为0(⾄少在此代码段中没有)。对于null列,iVal只是未初始化,访问它会产⽣编译器错误。
从同⼀ResultSet进⾏并发读取时,wasNull()有问题。不要沉迷于过去;)
@ryvantage我不认为开发⼈员会为NULL返回0⽽搞砸了,相反,他们做了正确的事情来避免在将空Integer值拆箱时会发⽣的NPE。
@sactiw遵循此逻辑,应该开发Java上的所有内容以避免NPE,事实并⾮如此。避免NPE是应⽤程序开发⼈员的责任,⽽不是语⾔内部API 的责任。
OMG为什么这么做,根本不返回NULL,0和null是两件⼤事
太刺激了! @ryvantage我发现⾃⼰做得这么多,以⾄于我只使⽤⼀个包装器类,该包装器类在构造函数中接受ResultSet,并且具有⾃⼰的getInt(etc)⽅法。
@sactiw如果返回参数是可为空的对象(Integer),则不会取消装箱。开发⼈员是错误的,因为null和0的值不同。因此,当值为null时返回0是错误的(并且确实使新⼿陷⼊了编写⽣产代码的API)。
@ryvantage尝试将返回值存储为原始类型,或者将其与原始类型进⾏⽐较,或者尝试将与⾮原始类型(整数类型)进⾏⽐较,看看吗?
@sactiw看到什么?这⾥没有要测试的东西。如果API是getInteger(),并且返回了Integer,则将没有取消装箱和NPE。没有什么可以测试。
@ryvantage编写⼀个简单的⽅法,例如Integer getInteger()并从中返回null,然后查看执⾏以下操作时会发⽣什么:int c =
getInteger();
@ryvantage ResultSet是原始Java类之⼀,⽽Java不⽀持⾃动拆箱。这也是⼀个⾮常低级的API,该API不应强制执⾏从Java Integer对象内部的数据库包装原始字节的潜在额外费⽤。可能存在⼀个参数,⽤于将getInteger添加到返回Integer的接⼝(甚⾄是Optional )。
@sactiw我知道任何可为空的对象都有NPE的风险,但是API⽅法本⾝不会抛出NPE的风险。您反对getInteger()的论点是反对null作为构造的⼀般论点。但是,只要Java中存在null并且只要数据库值为null,则该⽅法应返回。毫⽆争议:当值为null时返回0是不正确的。
@Richard我了解它的早期API,⽽摆脱getInt()将会是有问题的。但是,是的,添加getInteger()是⾮常明智的。他们之前已添加到API(请参阅:getBigDecimal())。
@ryvantage好的,我明⽩了,是的,有⼀个getInteger()⽅法确实有意义,顺便说⼀句,它们确实提供了⼀个通⽤的wasNull()⽅法,该⽅法可⽤于检查最后读取的列的值是否为NULL。
@sactiw,对。 wasNull()使代码看起来很糟糕,尽管哈哈。此外,(这是我的主要观点)对于想知道为
什么他们的数字不正确的新⼿来
说,API变得很困难。
我认为ResultSet API这样⼯作是完全错误的。从域的⾓度来看,值" 0"可能与" NULL"⾮常不同。如果0是⼀列的有效值(该值也可能不存在)怎么办。虽然这实际上看起来像是⾮常糟糕的数据库设计,哈哈。
另⼀个解决⽅案:
public class DaoTools {
static public Integer getInteger(ResultSet rs, String strColName) throws SQLException {
int nValue = rs.getInt(strColName);
return rs.wasNull() ? null : nValue;
}
}
我认为,这是多余的。如果列值实际上是NULL,则rs.getObject("ID_PARENT")应该返回Integer对象或NULL。因此,甚⾄应该可以执⾏以下操作:
if (rs.next()) {
Integer idParent = (Integer) rs.getObject("ID_PARENT");
if (idParent != null) {
iVal = idParent; // works for Java 1.5+
} else {
// handle this case
}
}
嗯,⾄少在我的情况下,问题在于调⽤getObject不⼀定返回Integer,这是由于使⽤(" Number")的oracle db Im中的列类型的性质。
Matt的相同问题...对于MySQL和Types.BIGINT(应映射到Long),getObject()⽅法返回0⽽不是null。
也可以做rs.getObject("ID_PARENT", Integer.class)
只需检查该字段是NULL还是不使⽤ResultSet#getObject()。⽤所需的任何空⼤⼩写值替换-1。
int foo = Object("foo") != null ? Int("foo") : -1;
或者,如果可以保证使⽤正确的数据库列类型,以使ResultSet#getObject()真正返回Integer(因此不能返回Long,Short或Byte),那么也可以将其类型转换为Integer。
Integer foo = (Integer) Object("foo");
不,但是在⾮null情况下,它将构造不必要的Integer对象。 (顺便说⼀句,⼤多数JDBC驱动程序在任何ResultSet⽅法调⽤期间都不会访问数据库...通常,直到所有数据通过⽹络传输时,您才不会获得ResultSet)。
这取决于获取⼤⼩。在⼤多数驱动程序中,默认值为10⾏,⼀旦检索到取回,将对其进⾏处理,但是直到处理完成后才检索下⼀次取回。
我很惊讶您的答案不是更好的答案:-)我投票赞成,因为这是避免⾮常棘⼿的不安全wasNull()⽅法的正确答案。对我来说,停⽌使⽤Java ;-)并继续使⽤VB.Net是⼀个补充性的原因,在该环境中RecordSet已经解决了这个简单的问题⼗多年了!
您可以简单地使⽤AFAIK
iVal = rs.getInt("ID_PARENT");
if (rs.wasNull()) {
// do somthing interesting to handle this situation
}
即使它为NULL。
只是Java Generics的更新。
您可以创建⼀个实⽤程序⽅法,以从先前强制转换的给定ResultSet中检索任何Java类型的可选值。
不幸的是,getObject(columnName,Class)不返回null,但是给定Java类型的默认值,因此需要2次调
bigdecimal转换为integerpublic < T > T getOptionalValue(final ResultSet rs, final String columnName, final Class< T > clazz) throws SQLException {
final T value = rs.getObject(columnName, clazz);
return rs.wasNull() ? null : value;
}
在此⽰例中,您的代码如下所⽰:
final Integer columnValue = getOptionalValue(rs, Integer.class);
if (columnValue == null) {
//null handling
} else {
//use int value of columnValue with autoboxing
}
很⾼兴获得反馈
您可以使⽤resultSet和具有Number类型的列名称来调⽤此⽅法。它将返回Integer值,或者返回null。数据库中的空值将不返回零
private Integer getIntWithNullCheck(ResultSet rset, String columnName) {
try {
Integer value = Int(columnName);
return rset.wasNull() ? null : value;
} catch (Exception e) {
return null;
}
}
您能否详细介绍⼀下这是如何解决问题的?
您可以使⽤resultSet和具有Number类型的列名称来调⽤此⽅法。它将返回Integer值,或者返回null。数据库中的空值将不会返回零。优秀的!将其编辑为答案(并在编辑后删除评论),您将获得⼀个不错的答案:)
为⽅便起见,您可以在ResultSet周围创建⼀个包装器类,当ResultSet通常不返回时,该包装器返回空值。
public final class ResultSetWrapper {
private final ResultSet rs;
public ResultSetWrapper(ResultSet rs) {
this.rs = rs;
}
public ResultSet getResultSet() {
return rs;
}
public Boolean getBoolean(String label) throws SQLException {
final boolean b = rs.getBoolean(label);
if (rs.wasNull()) {
return null;
}
return b;
}
public Byte getByte(String label) throws SQLException {
final byte b = rs.getByte(label);
if (rs.wasNull()) {
return null;
}
return b;
}
// ...
}
使⽤Java 8,您可以执⾏以下操作:
Long nVal = Optional.BigDecimal("col_name"))
.map(BigDecimal::longValue).orElse(null));
在这种情况下,如果SQL值为NULL,则确保nVal将为null(⽽不是零)。
但不适⽤于Int("col_name")
使⽤MSSQL数据源,这似乎不起作⽤。它需要附加检查if (rs.wasNull())
如果可以控制SQL,另⼀种不错的检查⽅法是在查询本⾝中为int列添加默认值。然后只需检查该值即可。
例如对于Oracle数据库,请使⽤NVL
SELECT NVL(ID_PARENT, -999) FROM TABLE_NAME;
然后检查
if (rs.getInt('ID_PARENT') != -999)
{
}
当然,这也是基于以下假设:在列中通常不会到该值。
我否决了这个答案,因为它很可能给很多⼈带来⿇烦。如果将int列定义为可为空,则它具有⼀组由正数,零,负数和NULL组成的值。在任何时间点,只要插⼊包含该幻数的有效数据⾏,所有突发事件都会变坏。它基本上执⾏幻数反模式。不要这样做。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。