Erro ao fazer consulta de compras num entre intervalos de datas

Boa noite.
Estou tentando fazer uma consulta no banco de dados (PostgreSql) onde tenho uma tabela de compras e ela tem um campo que armazena as datas das compras. Bem Estou tentando consultar todas as compras realizadas em um intervalos entre duas datas, mas a mesma rertonar estes erros:

primeiro aviso e este:

segundo aviso e este:

codigo do botao pesquisa:

private void jbPesquisaHistActionPerformed(java.awt.event.ActionEvent evt) {
//botao buscar compras por periodo

    try {
        //receber as datas.
        DateTimeFormatter formato = DateTimeFormatter.ofPattern("dd/MM/yyyy");

        LocalDate data_inicio = LocalDate.parse(jftDtInicial.getText(), formato);
        LocalDate data_fim = LocalDate.parse(jftDtFinal.getText(), formato);
        
        ComprasDao dao = new ComprasDao();
        List<Compras> lista = dao.listarComprasPorPeriodo(data_inicio, data_fim);
        System.out.println(lista);
        
        preencherTabela("select codigo_compra, num_nota, data_compra, nome, total_compra, obs from tb_compras "
                + "inner join tb_fornecedores on (cod_fornecedor = codigo_fornecedor) where data_compra between "+data_inicio+" and "+data_fim+" order by data_compra");

    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, "Digite Duas Datas Com Intervalo!");
    }
} 

codigo do metodo em Dao:

//metodo que filtra vendas por data
public List listarComprasPorPeriodo(LocalDate data_inicio, LocalDate data_fim) {
try {
//criando a lista.
List lista = new ArrayList<>();
//comando sql para lista os dados.
String sql = "select codigo_compra, num_nota, data_compra, nome, total_compra, obs from tb_compras "
+ “inner join tb_fornecedores on (cod_fornecedor = codigo_fornecedor) where data_compra between ? and ?”;

        PreparedStatement stmt = con.prepareStatement(sql);
        stmt.setString(1, data_inicio.toString());
        stmt.setString(2, data_fim.toString());
        
        ResultSet rs = stmt.executeQuery();

        while (rs.next()) {
            Compras obj = new Compras();
            Fornecedores f = new Fornecedores();

            obj.setCodigoCompra(rs.getInt("codigo_compra"));
            obj.setNumNota(rs.getInt("num_nota"));
            obj.setDataCompra(rs.getDate("data_compra"));
            f.setNome(rs.getString("nome"));
            obj.setTotalCompra(rs.getDouble("total_compra"));
            obj.setObs(rs.getString("obs"));
            
            obj.setFornecedor(f);

            lista.add(obj);
        }
        return lista;
    } catch (Exception erro) {
        JOptionPane.showMessageDialog(null, "Erro :" + erro);
        return null;
    }
}

Os campos de data estão como no banco? Dá a entender que eles são do tipo date, então não tem porque transformar o LocalDate em string, apenas passe-o diretamente, conforme a própria documentação indica:

stmt.setObject(1, data_inicio);
stmt.setObject(2, data_fim);

Lembrando que você deve usar o driver do PostgreSQL compatível com JDBC 4.2 para poder usar as classes do java.time.

Fiz as alterações, mais continua com o mesmo erro: estou usando o JDBC 4.2 compativel com PostgreSQL.

//metodo que filtra vendas por data
public List listarComprasPorPeriodo(LocalDate data_inicio, LocalDate data_fim) {
try {
//criando a lista.
List lista = new ArrayList<>();
//comando sql para lista os dados.
String sql = "select codigo_compra, num_nota, data_compra, nome, total_compra, obs from tb_compras "
+ “inner join tb_fornecedores on (cod_fornecedor = codigo_fornecedor) where data_compra between ? and ?”;

        PreparedStatement stmt = con.prepareStatement(sql);
        stmt.setObject(1, data_inicio.toString());
        stmt.setObject(2, data_fim.toString());
        
        ResultSet rs = stmt.executeQuery();

        while (rs.next()) {
            Compras obj = new Compras();
            Fornecedores f = new Fornecedores();

            obj.setCodigoCompra(rs.getInt("codigo_compra"));
            obj.setNumNota(rs.getInt("num_nota"));
            obj.setDataCompra(rs.getDate("data_compra"));
            f.setNome(rs.getString("nome"));
            obj.setTotalCompra(rs.getDouble("total_compra"));
            obj.setObs(rs.getString("obs"));
            
            obj.setFornecedor(f);

            lista.add(obj);
        }
        return lista;
    } catch (Exception erro) {
        JOptionPane.showMessageDialog(null, "Erro :" + erro);
        return null;
    }
}

dei um System.out.print para verificar o que o lista esta recebendo e o lista esta recebendo null e nao as datas que vai no data_inicio e data_fim.

isso e o que lista esta recebendo aintes de executar a linha do dao

run:
null
CONSTRUÍDO COM SUCESSO (tempo total: 19 segundos)

Não é para passar strings, é para passar o LocalDate diretamente. Assim:

stmt.setObject(1, data_inicio);
stmt.setObject(2, data_fim);

Se o campo do banco é DATE, você passa o LocalDate e o driver “se vira” para fazer a query. Não precisa chamar toString().

A coluna data_compra deve ser do tipo DATE ou TIMESTAMP mas no PreparedStatement você está passando String.
Tem que passar um objeto java.sql.Date.

no banco de dados esta como Date.

//metodo que filtra vendas por data na classe Dao
public List listarComprasPorPeriodo(LocalDate data_inicio, LocalDate data_fim) {
try {
//criando a lista.
List lista = new ArrayList<>();
//comando sql para lista os dados.
String sql = "select codigo_compra, num_nota, data_compra, nome, total_compra, obs from tb_compras "
+ “inner join tb_fornecedores on (cod_fornecedor = codigo_fornecedor) where data_compra between ? and ?”;

        PreparedStatement stmt = con.prepareStatement(sql);
        stmt.setObject(1, data_inicio);
        stmt.setObject(2, data_fim);
        
        ResultSet rs = stmt.executeQuery();

        while (rs.next()) {
            Compras obj = new Compras();
            Fornecedores f = new Fornecedores();

            obj.setCodigoCompra(rs.getInt("codigo_compra"));
            obj.setNumNota(rs.getInt("num_nota"));
            obj.setDataCompra(rs.getDate("data_compra"));
            f.setNome(rs.getString("nome"));
            obj.setTotalCompra(rs.getDouble("total_compra"));
            obj.setObs(rs.getString("obs"));
            
            obj.setFornecedor(f);

            lista.add(obj);
        }
        return lista;
    } catch (Exception erro) {
        JOptionPane.showMessageDialog(null, "Erro :" + erro);
        return null;
    }
}

acao do botao pesquisa:

private void jbPesquisaHistActionPerformed(java.awt.event.ActionEvent evt) {
//botao buscar compras por periodo

    try {
        //receber as datas.
        DateTimeFormatter formato = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        
        LocalDate data_inicio = LocalDate.parse(jftDtInicial.getText(), formato);
        LocalDate data_fim = LocalDate.parse(jftDtFinal.getText(), formato);
        
        
        ComprasDao dao = new ComprasDao();
        List<Compras> **lista** = dao.listarComprasPorPeriodo(data_inicio, data_fim);
        System.out.println(**lista**);
        
        preencherTabela("select codigo_compra, num_nota, data_compra, nome, total_compra, obs from tb_compras "
                + "inner join tb_fornecedores on (cod_fornecedor = codigo_fornecedor) where data_compra between "+data_inicio+" and "+data_fim+" order by data_compra");

    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, "Digite Duas Datas Com Intervalo!");
    }
}

a lista esta null.

Se a lista está null é porque caiu neste catch. Qual é o erro?

E porque tens a tua query repetida?

Quando postar código no fórum, formata ele:
formatacao-forum

Então ajusta as chamadas do teu PreparedStatement passando objetos do tipo Date e não do tipo String:

    PreparedStatement stmt = con.prepareStatement(sql);
    stmt.setDate(1, Date.valueOf(data_inicio));
    stmt.setDate(2, Date.valueOf(data_fim));

Só tenha certeza de utilizar java.sql.Date ao invés de java.util.Date.

depois da ultima mexida deixou de ser null a lista , ela esta agora assim

run:
[modelo.Compras@4fa25774, modelo.Compras@6e2e0a6a, modelo.Compras@24255cbe]
[modelo.Compras@571b29a0, modelo.Compras@296e524b, modelo.Compras@4a9e8f12]
[modelo.Compras@5bbaa1ad, modelo.Compras@4f45978f, modelo.Compras@dc2ad8b]

a segunda query e para preencher a tabela

Então a lista está correta, estás a ver o toString da tua classe Compras que por default mostra o nome da classe e o hashCode do objecto em hexadecimal. Se sobreescreveres o toString() com algo que faça sentido, vais ver o seu output.

Depois, o preenchimento da tabela deve usar a tua lista e não voltar a fazer o select…