[RESOLVIDO] Problemas para inserir um novo dado

Olá pessoas, estou com problemas para inserir dados no banco de dados. O Java exibe a seguinte mensagem de erro:

Exception in thread "main" java.lang.RuntimeException: org.postgresql.util.PSQLException: ERROR: relation 
"sequencia_contatos" does not exist
  Onde: PL/pgSQL function teste.funcao_contatos() line 3 at assignment
  at br.com.lobasfotworks.testejdbc.dao.ContatoDao.insere(ContatoDao.java:33)
  at br.com.lobasfotworks.testejdbc.TesteJDBC.main(TesteJDBC.java:28)
Caused by: org.postgresql.util.PSQLException: ERROR: relation "sequencia_contatos" does not exist
  Onde: PL/pgSQL function teste.funcao_contatos() line 3 at assignment
  at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2433)
  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2178)
  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:306)
  at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
  at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
  at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:155)
  at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:144)
  at br.com.lobasfotworks.testejdbc.dao.ContatoDao.insere(ContatoDao.java:29)
  ... 1 more

Ele relata que a q relação “sequencia_contatos” não existe e, para minha surpresa, quando faço a inserção direto no PGADMIN não acontece nenhum erro.

-- Sequencia para incrementar os id's dos contatos automaticamente
CREATE SEQUENCE sequencia_contatos INCREMENT BY 1;


-- Funcao para incrementar automaticamente o ID de cada contato inserido na tabela
CREATE OR REPLACE FUNCTION funcao_contatos()
RETURNS TRIGGER AS
$BODY$
  BEGIN
	  new.id := nextval('sequencia_contatos');
	
	  RETURN new;
  END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;


-- Uma tabela para guardar os meus contatos
CREATE TABLE contatos (
  id              BIGINT NOT NULL, -- # de identificacao de cada contato
  nome            VARCHAR(255),
  email           VARCHAR(255),
  endereco        VARCHAR(255),
  data_nascimento DATE,
  CONSTRAINT contatos_pk PRIMARY KEY (id)
);


-- A cada nova insercao, este gatilho incrementa automaticamente o ID de cada novo
-- contato.
CREATE TRIGGER contatos_trigger BEFORE INSERT
ON contatos
FOR EACH ROW
EXECUTE PROCEDURE funcao_contatos();

Abaixo o meu código da classe principal. Eu realmente não entendi o que tem de errado nele :disappointed_relieved:

public class TesteJDBC {

  public static void main(String[] args)  throws ParseException{
	  ContatoDao contatoDao;
	  Contato contato;
	  SimpleDateFormat dateFormat;
	
	  contato = new Contato();
	  contato.setNome("Ana Maria");
	  contato.setEmail("amaria@outlook.com");
	  contato.setEndereco("Rua dos Lobos, 202");
	
	  dateFormat = new SimpleDateFormat("dd/MM/yyyy");
	
	  contato.setDataNascimento(Calendar.getInstance());
	  contato.getDataNascimento().setTimeInMillis(dateFormat.parse("04/08/1993").getTime());
	
	  contatoDao = new ContatoDao();
	  contatoDao.insere(contato);
  }

}

O nome do seu banco está correto?

Aqui diz que a tabela sequencia_contatos não existe.
Mostra aqui a sua classe que contém os métodos com as queries/instruções SQL.

O nome da tabela onde está sendo inserido os dados está correto?

Bom, o código fonte da classe que insere os dados é esse aqui. É para um exercício de programação para internet. A parte da conexão está OK, senão o construtor sequer
instanciaria esta classe. Eu não sei o que fazer, tipo, sem os triggers ela está funcionando,
mas ele pediu para gente implementar pelo menos um trigger no exercício.

public class ContatoDao {
  private Connection conexao;

  public ContatoDao() {
  	  conexao = new ConnectionFactory().getConnection();
  }

  public void insere(Contato contato) {
	  PreparedStatement pstmt;
	  String sql;
	
	  sql = 	"INSERT INTO teste.contato(nome, email, endereco, dataNascimento) " +
			    "VALUES " +
			    "(?,?,?,?)";
	
	  try {
		  pstmt = conexao.prepareStatement(sql);
		  pstmt.setString(1, contato.getNome());
		  pstmt.setString(2, contato.getEmail());
		  pstmt.setString(3, contato.getEndereco());
		  pstmt.setDate(4, 
				  new Date(contato.getDataNascimento().getTimeInMillis())
		  );
		  pstmt.execute();
		  pstmt.close();
	  }
	  catch (SQLException e) {
		  throw new RuntimeException(e);
	  }
  }
}

Logo abaixo está o código da classe que instancia uma nova conexão para o banco de dados:

public class ConnectionFactory {

  public Connection getConnection() {
	  Connection conexao;
	  Properties info;
	  String url;
	
	  try {
		  url = "jdbc:postgresql://localhost:5432/postgres";
		  info = new Properties();
		  info.setProperty("user", "postgres");
		  info.setProperty("password", "******");
		  conexao = DriverManager.getConnection(url, info);
		
		  return conexao;
	  }
	  catch (SQLException e) {
		  // Transformar a exception SQL em uma RUNTIME para desacoplar
		  // a API do SQL da minha aplicacao
		  throw new RuntimeException(e);
	  }
    }

  }
1 curtida

O pior é que quando eu executo o script de inserção direto no PGADMIN ele não dá erro nenhum. Isso só está acontecendo no Java. Isso está me deixando com a pulga atrás da orelha.

SET SEARCH_PATH TO teste; -- garantir que o esquema padrao seja teste

INSERT INTO teste.contatos (nome, email, endereco, dataNascimento)
VALUES
('um_nome', 'algum@email.com', 'Rua qualquer, 000', to_date('01/01/2018', 'DD/MM/YYYY'));
1 curtida

O nome do seu banco de dados é postgres mesmo?

Essa query é a query do seu metodo INSERT?
Eu falo do método que é parecido com isso.

public void inserir(Pessoa pessoa){
     String sql = "INSERT INTO teste.contatos (nome, email, endereco, dataNascimento) VALUES (?, ?, ?, ?);";
     // Resto do código.
}

A query que postou é a mesma que tá sendo usada dentro do método?

Sim, o nome do banco é postgres.

O engraçado é que, foi só eu mudar a string dentro da função “nextval” e colocar o nome do esquema (no caso teste) antes do nome da sequência que a inserção passou a funcionar. Agora o por quê disso eu não sei. XD

CREATE OR REPLACE FUNCTION contato_function()
RETURNS TRIGGER AS
$BODY$
    BEGIN
	    -- Pegando o novo valor da sequencia
	    NEW.cid := nextval('teste.sequencia_contatos');
	
	    RETURN NEW;
    END;
$BODY$
LANGUAGE 'plpgsql';
1 curtida

Beleza, só marca a sua resposta como correta!!