[RESOLVIDO]Dados NULL estão vindo com "0"

Bom dia pessoal,

Como foram de feriado? Pra começar o dia estou com uma dúvida aqui. Estou trabalhando com um banco de dados nada normalizado. Não estou usando nenhum framework para buscar os dados, estou usando apenas uma classe DAO. O problema é tenho informações no meu banco que podem ter valores NULOS e estão vindo “0”. Coloquei um comentário na minha DAO:

[code]public List recuperaChuvaOrdenadaData() throws SQLException {

    PreparedStatement stmt = this.connection.prepareStatement("SELECT * FROM Chuvas ORDER BY Data");  
    ResultSet rs = stmt.executeQuery();  
    List<Chuva> list = new ArrayList<Chuva>();  
      
    while (rs.next()){  
    	Chuva chuva = new Chuva();  
    	chuva.setDataChuva(rs.getDate("Data"));  
    	chuva.setChuva01(rs.getDouble("Chuva01")); // é nessa linha que acontece a problema. Os valores que precisava que viesse NULL está vindo "0"

list.add(chuva);
}

    rs.close();  
    stmt.close();  
    return list;     
 }  

[/code]

E a minha entidade:

[code]public class Chuva {

private Date dataChuva;
private Double chuva01;

    public Date getDataChuva() {
	return dataChuva;
}
public void setDataChuva(Date dataChuva) {
	this.dataChuva = dataChuva;
}
    public Double getChuva01() {
	return chuva01;
}
public void setChuva01(Double chuva01) {
	this.chuva01 = chuva01;
}[/code]

isso pode ser coisa do servidor, as vezes você precisa configurá-lo pra não “forçar” valores numéricos que deveriam ser nulos para zeros.

por exemplo… no JBoss 7 você precisa adicionar o parâmetro “-Dorg.apache.el.parser.COERCE_TO_ZERO=false” nos VM Arguments

mas também pode não ser isso… você ja leu o que a documentação diz sobre o método getDouble? talvez tenha algo lá

Dá uma olhada na documentação do método do resultset.
Ele retorna 0 se os dados forem null mesmo.

http://docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html#getDouble(int)

Realmente… O getDouble retorna zero. Estou procurando uma solução aqui, mas alguém tem uma aí?

ja tentou com o getObject?

Cara coloca um if ai e pronto.

Tem esse método aqui da classe resultset wasNull que parece que retorna um boolean dizendo se a coluna lida é null.

Mas parece que você primeiro deve chamar o getDouble.
Dai faz um if, que se for zero você testa com esse método.

http://docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html#wasNull()

Se você sabe que um campo é nullable, você tem de testar antes com “wasNull”. Troque

chuva.setChuva01(rs.getDouble("Chuva01"));

para

double d = rs.getDouble ("Chuva01");
if (rs.wasNull())
     chuva.setChuva01 (null);
else
     chuva.setChuva01 (d);

O recomendado, obviamente, é criar um método que faça essa parte chata para você. Algo como:

public static Double getNullableDouble (ResultSet rs, String nomeCampo) {
     double d = rs.getDouble (nomeCampo);
     if (rs.wasNull()) 
         return null;
     else
         return d;
}

e você troca seu código por

chuva.setChuva01 (getNullableDouble (rs, "Chuva01"));

Em particular não gosto de getObject.

Esse método é implementado pelo driver do SQL, não pela própria Oracle, e não é muito bem especificado.

O resultado líquido é que cada driver SQL implementa isso de um jeito diferente, e acabamos tendo resultados que dependem tanto do banco usado quanto do driver usado, o que dá uma dor de cabeça dos infernos.

A idéia do usuário entanglement e bem interessante.
Talvez colocar com um método genérico ou uns overrides, pois esse mesmo comportamento ocorre com int, long, float. além de double.

[quote=entanglement]Se você sabe que um campo é nullable, você tem de testar antes com “wasNull”. Troque

chuva.setChuva01(rs.getDouble("Chuva01"));

para

double d = rs.getDouble ("Chuva01");
if (rs.wasNull())
     chuva.setChuva01 (null);
else
     chuva.setChuva01 (d);

O recomendado, obviamente, é criar um método que faça essa parte chata para você. Algo como:

public static Double getNullableDouble (ResultSet rs, String nomeCampo) {
     double d = rs.getDouble (nomeCampo);
     if (rs.wasNull()) 
         return null;
     else
         return d;
}

e você troca seu código por

chuva.setChuva01 (getNullableDouble (rs, "Chuva01")); [/quote]

Muito Bom galera!!! Obrigadão!

Então ficou assim:

Criado o método que faz a verificação:

public static Double getNullableDouble (ResultSet rs, String nomeCampo) {
     double d = rs.getDouble (nomeCampo);
     if (rs.wasNull()) 
         return null;
     else
         return d;
}

e trocado o código por

chuva.setChuva01 (getNullableDouble (rs, "Chuva01"));

RESOLVIDO!!!

Opa…

Bom… estou com um problema meio inverso…
No meu caso me deparei com um getDouble que retorna null mesmo… não faz a conversão para ZERO conforme documentação.

Um dos motivos é que o driver não reconheceu o SQL NULL por algum motivo…

Estou vendo se há alguma configuração para isso ou se o driver usado é muito antigo… mas alguém, já se deparou com isso?

vlw

Qual o banco ?

Oracle 10g.

O aplicativo fica no IBM Websphere