Postgres NullIf e Date to_char

Olá!

Estou com um problema ao chamar meu SQL em um Jframe no java.
Eu tenho o seguinte:

SET datestyle TO postgres, dmy; SELECT codigoanimal, NULLIF(codigomae_codigoanimal, '0'), CASE WHEN sexo = 'M' THEN 'Macho' WHEN sexo = 'F' THEN 'Fêmea' END AS sexoalterado, CASE WHEN origemanimal = 'N' THEN 'Nativo' WHEN origemanimal = 'C' THEN 'Comprado' END AS origemalterada, NULLIF(datanascimento, '0002-11-30 BC'), NULLIF(dataaquisicao, '0002-11-30 BC'), CASE WHEN statusanimal = 'R' THEN 'No rebanho' WHEN statusanimal = 'V' THEN 'Vendido' END AS statusalterado FROM animal;

Mas o JDBC não aceita settar o datestyle, então fiz isso:

SELECT codigoanimal, NULLIF(codigomae_codigoanimal, '0'), CASE WHEN sexo = 'M' THEN 'Macho' WHEN sexo = 'F' THEN 'Fêmea' END AS sexoalterado, CASE WHEN origemanimal = 'N' THEN 'Nativo' WHEN origemanimal = 'C' THEN 'Comprado' END AS origemalterada, to_char(datanascimento,'DD/MM/YYYY'), to_char(dataaquisicao,'DD/MM/YYYY'), NULLIF(datanascimento, '0002-11-30 BC'), NULLIF(dataaquisicao, '0002-11-30 BC'), CASE WHEN statusanimal = 'R' THEN 'No rebanho' WHEN statusanimal = 'V' THEN 'Vendido' END AS statusalterado FROM animal;

Maaas ai vão aparecer duas vezes as datas… Tem como eu ‘mesclar’ isso? Ou tenho que dar um jeito no Java?

Quando você seta a data, dá algum erro?

Não, eu passo como string e uso um DateFormat que chamo quando vou inserir no banco, bem assim:

private Date formatarData(String data) throws ParseException { DateFormat formatar = new SimpleDateFormat("dd/MM/yyyy"); return new Date(formatar.parse(data).getTime()); }

Eu estou pegando os dados assim:

public List<Animal> findAnimais() throws SQLException { List<Animal> animais = new ArrayList<Animal>(); String select = "SELECT codigoanimal, NULLIF(codigomae_codigoanimal, '0'), " + "CASE WHEN sexo = 'M' THEN 'Macho' WHEN sexo = 'F' THEN 'Fêmea' END AS sexoalterado, " + "CASE WHEN origemanimal = 'N' THEN 'Nativo' WHEN origemanimal = 'C' THEN 'Comprado' END AS origemalterada," + "datanascimento, dataaquisicao, " + "CASE WHEN statusanimal = 'R' THEN 'No rebanho' WHEN statusanimal = 'V' THEN 'Vendido' END AS statusalterado " + "FROM animal"; PreparedStatement stmt = getConnection().prepareStatement(select); ResultSet rs = stmt.executeQuery(); while (rs.next()) { Animal animal = new Animal(); animal.setCodigo(rs.getInt("codigoanimal")); animal.setCodigoMae(rs.getInt("nullif")); animal.setSexoSelect(rs.getString("sexoalterado")); animal.setOrigemSelect(rs.getString("origemalterada")); //animal.setSexo(rs.getString("sexo_alterado").charAt(0)); //animal.setOrigem(rs.getString("origemanimal").charAt(0)); animal.setDataNascimento(rs.getDate("datanascimento")); //animal.setDataNascimento(rs.getString("datanascimento")); animal.setDataAquisicao(rs.getDate("dataaquisicao")); animal.setstatusSelect(rs.getString("statusalterado")); //animal.setstatus(rs.getString("statusanimal").charAt(0)); animais.add(animal); } rs.close(); stmt.close(); return animais; }

Então vem o problema, o Nullif não filtra corretamente e a data volta corretamente.

Você está usando preparedStatement e ainda assim quer jogar uma String?
Use o setDate do preparedStatement para passar a data.

Seria algo como:

Isso? Eu to importanto tudo certinho, mas aá dando NullPointerException…

Nullpointer nesta linha?
Consegue debuggar?

Não muito bem… O que eu tenho que observar aqui?

se animal possui valor e se dataNascimento tambem

Primeira passagem - atributos de animal
datanascimento: null
dataaquisicao: null
observacao: null
statusselect: null
codigoanimal: 5
origemselect: "Nativo"
sexoselect: "Macho"
sexo: ''
origem: '‘
status:’'
codigomae: 0

passando sobre a expressão:
datanascimento: null
dataaquisicao: null
observacao: null
statusselect: null
codigoanimal: 5
origemselect: "Nativo"
sexoselect: "Macho"
sexo: ''
origem: '‘
status:’'
codigomae: 0

Passando sobre a expressão novamente:
datanascimento: null
dataaquisicao: null
observacao: null
statusselect: null
codigoanimal: 5
origemselect: Sem contexto atual (quadro de pilha)
sexoselect: "Macho"
sexo: ''
origem: '‘
status:’'
codigomae: 0

Ai ele passa mais umas 3 vezes pelo thread e cai nessa linha: getUncaughtExceptionHandler().uncaughtException(this, e); antes de pegar a NullPointer

Bom, se datanascimento é null, então aí está o erro.
Como você preenche esta variável?

No DAO:

public void salvar(Animal animal) throws SQLException { String insert = "INSERT INTO animal(codigoanimal, sexo, origemanimal, datanascimento, dataaquisicao, statusanimal, " + "observacaoanimal, codigomae_codigoanimal) VALUES (NEXTVAL('seq_animal'), ?, ?, ?, ?, ?, ?, ?)"; save(insert, /**animal.getCodigo(),*/ animal.getSexo(), animal.getOrigem(), animal.getDataNascimento(), animal.getDataAquisicao(), animal.getStatus(), animal.getObservacao(), animal.getCodigoMae()); }

No Controller:

[code]public void salvar(/**int codigoAnimal,*/
char sexo, char origem, String dataNascimento,
String dataAquisicao, char status, String observacao, int codigoMae) throws SQLException, ParseException {

    Animal animal = new Animal();
    //animal.setCodigo(codigoAnimal);
    animal.setSexo(sexo);
    animal.setOrigem(origem);
    animal.setDataNascimento(formataData(dataNascimento));
    animal.setDataAquisicao(formataData(dataAquisicao));
    animal.setstatus(status);
    animal.setObservacao(observacao);
    animal.setCodigoMae(codigoMae);

    new AnimalDao().salvar(animal);
}[/code]

No Frame:

private void onClickSalvar() throws ParseException { AnimalController ac = new AnimalController(); try { ac.salvar(/**Integer.parseInt(txtCodigoAnimal.getText()),*/ sexo, origem, formTxtNascimento.getText(), formTxtAquisicao.getText(), localizacao, areaObservacao.getText(), Integer.parseInt(txtCodigoMae.getText())); JOptionPane.showMessageDialog(this, "Animal salvo com sucesso!"); clearFields(); }

Ali no Controller eu tenho o formatarData.

Vamos por partes.
Percebo que você possui uma String para data. Isso não é bacana.
Está trabalhando com Swing, existem determinados componentes que “desenham” calendários e apresentam a data conforme a região (locale) selecionado.
um dos mais conhecidos (e simples)
http://www.java2s.com/Code/Java/Swing-Components/JavaDateChooserComboBox.htm

Acredito que com isto, mas uns poucos ajustes, tudo funcionará.

Eu só estou usando a String se torna mais fácil para o usuário inserir o dado mesmo, mas o DateFormat insere no banco como um Date, como é especificado na minha classe Animal:

[code]public Date getDataNascimento() {
return dataNascimento;
}

public void setDataNascimento(Date dataNascimento) {
    this.dataNascimento = dataNascimento;
}

public Date getDataAquisicao() {
    return dataAquisicao;
}

public void setDataAquisicao(Date dataAquisicao) {
    this.dataAquisicao = dataAquisicao;
}[/code]

É que a minha aplicação já está praticamente pronto, eu só quero corrigir esses pequenos erros agora… Eu comecei com Swing a bem pouco tempo, ainda não tenho um bom conhecimento pra fazer tudo certinho, a maioria do que fiz é baseado em exemplos que encontrei…

Beleza, deixa eu ver se consigo te ajudar.
Você precisa pegar uma String “dd/MM/yyyy” e transformar em java.sql.Date, isto?
Se for isto, pode tentar assim:

//metodo
String data = JOptionPane.showInputDialog("Data");
DateFormat d = new SimpleDateFormat("dd/MM/yyyy");
        try {
            Date dt = d.parse(data);
//aqui você pega a data no "tipo" correto.
            java.sql.Date dtSql = new java.sql.Date(dt.getTime());
            System.out.println(dtSql);
        } catch (ParseException ex) {
            Logger.getLogger(RecsData.class.getName()).log(Level.SEVERE, null, ex);
        }

É isso sim, mas eu já estou transformando…

Quando eu insiro os dados, uso o seguinte:

private Date formatarData(String data) throws ParseException { DateFormat formatar = new SimpleDateFormat("dd/MM/yyyy"); return new Date(formatar.parse(data).getTime()); }

Ai quando eu chamo o método salvar, eu faço o seguinte:

Isso funciona perfeitamente.

O meu problema é na hora da consulta no banco, eu gostaria de retornar a data em padrão brasileiro e quando for uma certa data (0002-11-30 BC), eu quero que a consulta venha em branco… Pra isso, to usando NULLIF e DATE TO_CHAR, mas infelizmente, na aplicação não funciona igual funciona no pgAdmin.

Não tem essa necessidade.
Pega a data, no formato do banco, e reconverte.
Quando o BD manda a data, ela é uma java.sql.Date.
Você pode inverter a formatação, mais ou menos assim

public String sqlToPadrao(java.sql.Date dtSql){
            Date dtPadrao = new Date(dtSql.getTime());
            String dataRecebida = d.format(dtPadrao);
            return dataRecebida;
}

E no animal

animal.setDataNascimento(sqlToPadrao(data_que_o_bd_devolveu));

Mas o método format não fuinciona pra java.sql.Date…

public String sqlToPadrao(java.sql.Date dtSql) { Date dtPadrao = new Date(dtSql.getTime()); String dataRecebida = dtSql.format(dtPadrao); return dataRecebida; }

No caso os parâmetros dele são: String format, Object… args, não?

[quote=muniquewassem]Mas o método format não fuinciona pra java.sql.Date…

public String sqlToPadrao(java.sql.Date dtSql) { Date dtPadrao = new Date(dtSql.getTime()); String dataRecebida = dtSql.format(dtPadrao); return dataRecebida; }

No caso os parâmetros dele são: String format, Object… args, não?[/quote]
Por isso você vai converter em java.util.Date…
//recebe um date do java.sql

public String sqlToPadrao(java.sql.Date dtSql) { //cria um java.util.Date java.util.Date dtPadrao = new Date(dtSql.getTime()); //cria um dateFormat DateFormat dtPadrao = new SimpleDateFormat("dd/MM/yyyy"); //faz a formatação String dataRecebida = dtSql.format(dtPadrao); return dataRecebida; }

Ahhh sim!

public String sqlToPadrao(java.sql.Date dtSql) { //cria um java.util.Date java.util.Date dtPadraoOut = new Date(dtSql.getTime()); //cria um dateFormat DateFormat dtPadrao = new SimpleDateFormat("dd/MM/yyyy"); //faz a formatação String dataRecebida = dtPadrao.format(dtPadraoOut); return dataRecebida; }

Só mudei o nome da variável de util.Date, porque tava igual o do DateFormat.

Tá, agora no DAO, você me disse pra jogar:

Eu fiz: animal.setDataNascimento(sqlToPadrao(dataNascimento));
Mas não deu certo porque não tenho essa variável no DAO… Mas tudo bem, arrumei um jeito:

Mas continua me retornando NullPointerException…

Quando você aplica uma função em uma coluna ela perde o nome. Você precisa “renomea-la” usar “as” para ela manter o nome anterior.

tente isso

SELECT codigoanimal, NULLIF(codigomae_codigoanimal, '0'), CASE WHEN sexo = 'M' THEN 'Macho' WHEN sexo = 'F' THEN 'Fêmea' END AS sexoalterado, CASE WHEN origemanimal = 'N' THEN 'Nativo' WHEN origemanimal = 'C' THEN 'Comprado' END AS origemalterada, to_char(datanascimento,'DD/MM/YYYY') AS datanascimento, to_char(dataaquisicao,'DD/MM/YYYY') AS dataaquisicao, NULLIF(datanascimento, '0002-11-30 BC'), NULLIF(dataaquisicao, '0002-11-30 BC'), CASE WHEN statusanimal = 'R' THEN 'No rebanho' WHEN statusanimal = 'V' THEN 'Vendido' END AS statusalterado FROM animal;