RESOLVIDO - ResultSet em um ArrayList e após, um Insert ou Update no Banco Postgresql

Pessoal,
boa noite!

Poderiam me ajudar a ver se esta minha ideia é a melhor a ser feita ?

Eu tenho um Banco postgresql no linux e um Banco postgresql no Windows.

O que eu preciso é: selecionar dados específicos do postgresql do Linux e inserir novos ou update em já existentes no postgresql do Windows. Isso, pq o postgresql do windows é um banco local, separado justamente para consultas, sem que haja acesso direto no banco quente que é do linux.

Ai para isso, pensei o seguinte: efetuar o select, salvar os dados em um arraylist e em seguida, utilizar este arraylist para efetuar o insert ou o update no banco local.

Seria esta a melhor maneira ? Este processo também deverá correr de 1 em 1 hora, efetuando inserção ou atualização dos registros que fiz o select inicialmente.

Peço a ajuda de todos, pois, não sou muito pró em programação. Consigo criar a conexão e chego até o select, agora o restante do processo, não consigo seguir em frente, por não saber como fazer.

Agradeço a atenção e se possível, a ajuda de todos.

Obrigado.

Vamos supor que você conhece bem o SQL, então caberia buscar compreender a contrapartida em java.
Como eu não tenha habilidade nesse negócio, vou tentar contribuir com uma ideia.

Se você sabe quais são as exigências de inserção e atualização e consegue conectar normalmente, nos dois bancos de dados use a classe timer para gerenciar a atualização.

Crie uma interface para simplificar o processo e adicione funcionalidades e acordo com sua necessidade.

Use a classe Timer, para fins de atualização

import java.awt.event.ActionEvent;
import javax.swing.Timer;


public class Crisis extends javax.swing.JFrame {

    private static Timer atualizaServidor;

    public Crisis() {
        initComponents();
        config();

    }

    private void config() {
        //"relógio" configurado para realizar uma tarefa a cada uma hora
        atualizaServidor = new Timer(1000 * 3600, (ActionEvent e) -> {
            /*crie todas as requisições necessárias, agrupe em um método chame-o aqui, sendo que os processos serão executado a cada uma hora
            considerando a queda de energia, você deve desenvolver uma forma para a qual a aplicação
            inicie junto com o sistema operacional hospedeiro
             */
            System.out.println("Servidor atualizado");
        });
        atualizaServidor.start();
        
        btnParar.addActionListener((ActionEvent e) -> {
            atualizaServidor.stop();
        });
        
        btnReiniciar.addActionListener((ActionEvent e) -> {
            atualizaServidor.start();
        });
    }

//restante da codificação desnecessária

não entendi direito se é isto que precisa, mas se precisa de tempos em tempos copiar o
conteúdo de um banco para outro, faça o DUMP de todo o banco ou de tabelas especificas e salve em um arquivo , e no outro micro leia este arquivo e faça a inserção neste outro banco de dados . tem varios exemplos de como fazer isso, como abaixo:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
 
import java.sql.SQLException;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
 
public class Database  {
 
    private static final String DRIVER_NAME = "com.mysql.jdbc.Driver";
 
    static
    {
        try
        {
            Class.forName(DRIVER_NAME).newInstance();
            System.out.println("*** Driver loaded");
        }
        catch(Exception e)
        {
            System.out.println("*** Error : "+e.toString());
            System.out.println("*** ");
            System.out.println("*** Error : ");
            e.printStackTrace();
        }
 
    }
 
    private static final String URL = "jdbc:mysql://localhost/mydatabase";
    private static final String USER = "root";
    private static final String PASSWORD = "password";
    private static String INSTRUCTIONS = new String();
 
    public static Connection getConnection() throws SQLException
    {
        return DriverManager.getConnection(URL, USER, PASSWORD);
    }
 
    public static void resetDatabase() throws SQLException
    {
        String s            = new String();
        StringBuffer sb = new StringBuffer();
 
        try
        {
            FileReader fr = new FileReader(new File("mySQLFile.sql"));
            // be sure to not have line starting with "--" or "/*" or any other non aplhabetical character
 
            BufferedReader br = new BufferedReader(fr);
 
            while((s = br.readLine()) != null)
            {
                sb.append(s);
            }
            br.close();
 
            // here is our splitter ! We use ";" as a delimiter for each request
            // then we are sure to have well formed statements
            String[] inst = sb.toString().split(";");
 
            Connection c = Database.getConnection();
            Statement st = c.createStatement();
 
            for(int i = 0; i<inst.length; i++)
            {
                // we ensure that there is no spaces before or after the request string
                // in order to not execute empty statements
                if(!inst[i].trim().equals(""))
                {
                    st.executeUpdate(inst[i]);
                    System.out.println(">>"+inst[i]);
                }
            }
   
        }
        catch(Exception e)
        {
            System.out.println("*** Error : "+e.toString());
            System.out.println("*** ");
            System.out.println("*** Error : ");
            e.printStackTrace();
            System.out.println("################################################");
            System.out.println(sb.toString());
        }
 
    }

   ou,

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import com.ibatis.common.jdbc.ScriptRunner;

/**
 *
 @author Dhinakaran Pragasam
 */
public class RunSqlScript {
	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String[] args) throws ClassNotFoundException,
		SQLException {

		String aSQLScriptFilePath = "path/to/sql/script.sql";

		// Create MySql Connection
		Class.forName("com.mysql.jdbc.Driver");
		Connection con = DriverManager.getConnection(
			"jdbc:mysql://localhost:3306/database", "username", "password");
		Statement stmt = null;

		try {
			// Initialize object for ScripRunner
			ScriptRunner sr = new ScriptRunner(con, false, false);

			// Give the input file to Reader
			Reader reader = new BufferedReader(
                               new FileReader(aSQLScriptFilePath));

			// Exctute script
			sr.runScript(reader);

		} catch (Exception e) {
			System.err.println("Failed to Execute" + aSQLScriptFilePath
					+ " The error is " + e.getMessage());
		}
	}
}

da pra ter uma idéia, depois é somente alterar de acordo com seu banco, URL, nome de arquivo etc.
quanto ao tempo que precisa fazer de hora em hora, tem ai exemplo da classe TImer.

Marcelo e addller
Obrigado pelas dicas.
Achei interessante a parte do time de 1 em 1 hora e também o processo que o Marcelo descreveu. Vou estudar os dois para me ajudar no que preciso.

Está parte do arquivo Marcelo, tinha pensado nisso, mas, como são servidores diferentes, preciso fazer um SFTP para jogar o arquivo de um servidor para o outro e não queria fazer isso, por isso que pensei no caso do array. Pois, um servidor e Linux do outro e Windows.

Agora aproveitando a ajuda de vocês se possível, gostaria de um exemplo como funciona o UPSERT do PostgreSQL caso saibam ou como eu faço o insert se o registro não existe e Update se ele existir.

Os dados que serão inseridos sempre serão os mesmos, porém o que altera e a hora de início e fim, isto é, estou capturando horários de início e fim de rotinas específicas então pode ser que o que eu inseri já tenha horário de início mas não tenha hora fim, quando tiver, ele apenas vai fazer o update deste registro.

Eu sei como funciona um insert simples e um update simples, agora com esta instrução de insert se não existir e update se existe não sei fazer.

Será que vcs poderiam me mostrar um exemplo de como funcionária isso?

Muito obrigado.

hum… bom, ai pelo que você precisa comparar hora de inicio , fim, etc, no meu ponto de vista, pra te auxiliar teria que entender melhor como funciona este projeto ! quanto a copiar o arquivo de um micro para o outro, um win/linux, realmente da um pouco de trabalho no linux, o que você poderia simplificar se tiver rodando o SAMBA, daria muito menos trabalho em relação a copiar arquivos etc, quanto a
comparar rotinas especificas, ai complica. se quiser explicar melhor exatamente o que e como
precisa comparar determinados arquivos, fica melhor !

Agora aproveitando a ajuda de vocês se possível, gostaria de um exemplo como funciona o UPSERT do PostgreSQL caso saibam ou como eu faço o insert se o registro não existe e Update se ele existir.

especificamente em PostgreSQL não sei como funciona, mas em meu sistema trato direto no SQL o que nao importa se é PostGreSQL, Mysql etc… tenho por exemplo um cadastro, quando vou alterar este cadastro, tenho um boolean que altero para true, ex emEdicao = true , e tenho um metodo “cadastro” , neste metódo tenho um condicional, de acordo com true ou false, faço o INSERT ou o UPDATE.

Marcelo,
E assim:

Eu tenho alguns Jobs de processamento que rodam em determinados horários, então, quando eu fizer o select posso pegar essa rotina apenas com a hora de início dela, não vou ter a final pq ela ainda não terminou o processamento, por isso, sempre vou fazer um select e quando ela tiver terminada, faço o update no banco neste registro adicionando o fim do processamento. Ex:

Fiz o select e veio isso pra mim:
Job1;170629 ;1706290030;;

Os campos são: job, dia do processamento, data e hora de inicio, data e hora de fim.

Só select acima não tenho hora de fim, porém já inseri este registro no banco.

Em um próximo select, pode ser que este registro já venha assim:
Job1; 170629;1706290030;1706290100

No antigo select , já tinha este registro mas não tinha a hora final. Agora no novo select, já tenho ele com a hora final, então só preciso atualizar a hora final dele no banco. E assim vai ficar sendo feito de hora em hora, pois são diversas rotinas e elas processam no decorrer de um dia para o outro.

Consegui explicar melhor?

Obrigado novamente.

Bruno, você precisa estudar as tecnologias e vai levar tempo.
Para fins de verificação você pode usar trigger.
Sua dificuldade maior é com SQL, procure aprender sobre ela, pois no geral é a forma de comunicação com o banco de dados, seja ela, em java, php, etc.
Há outro problema, você vai precisar estudar sobre Entidade -> Relacionamento, Constraints etc.
Fazer bem feito, este é o foco.
Começe assistindo vídeos no youtube, não precisa ser somente de Postgres.
Se tiver com alguma dúvida tem só site w3schools, com explicações e exemplos.
A melhor dica que posso fornecer é que você tem que estudar teoria dos conjuntos e que veja todas as requisições como uma tabela, por exemplo:
Fez uma requisição e veio apenas um valor, será uma tabela com uma linha e uma coluna, este tipo de avaliação é feita para compreender o join.
Sugestão: https://www.youtube.com/watch?v=_ccMbzh9Ji0&list=PLAF4831DDBDB8E841

agora ficou mais fácil… bom, exemplo:

Fiz o select e veio isso pra mim:
Job1;170629 ;1706290030;;

pensando aqui acho que não teria dificuldades não, como eu faria por exemplo ::

private static Integer retornoResultSet(ResultSet resultset, String colunaHoraFinal) throws SQLException {

    int valor = resultset.getInt(colunaHoraFinal);
    if (resultset.wasNull()) {
       // insert aqui
        return null;
    } else {
    // update aqui
      return null;
 }
    return Integer.valueOf(valor);
} 

ou ex ::

String query = select horaFinal from tabela where nomeTarefa = Job1
ResultSet rs = stmt.executeQuery(query);
if (rs.next()) {
      if (!rs.wasNull()) {
       // update aqui
   } else {
      // insert aqui
} 

algo assim…entendeu

Porque fazer essa complicação de manter 2 bancos ? Porque não acessar o banco no Linux diretamente ?

este tipo de particularidade existe, tenho um sistema em um lugar, por diversos motivos não consigo acesso a determinados horários e preciso deste banco de dados em outro computador .

Use uma ferramenta de ETL então:

com o Talend por exemplo você pode inclusive exportar a rotina para uma classe Java e usar no seu projeto.

Marcelo,
Obrigado pela dicas , vou trabalhar com elas e ver o que vai dar. Depois posto aqui.

rmendes,
Hoje eu já acesso direto ele, porém, ele é um banco online aonde as rotinas que são processadas ou que dão erro já são inseridas em tempo real. Como é um banco de produção, não quero correr o risco de dar algum problema. Por isso, prefiro fazer com que a minha rotina faça a extração e carregue um banco local que não tem acesso nada, minimizando assim um possível impacto. E por isso que estou usando o array para fazer tudo de uma única vez, ao invés de extrair para um arquivo.

Pessoal,
ajuda para um novato, estou fazendo o meu select e a inclusão na lista desta forma:

static void lista(String odateMov) {

		String sql = "SELECT  order_id,"
                                    + "   job_name,"
				+ "      odate,"
				+ " start_time,"
				+ "   end_time "
				+ "  FROM a"+odateMov+"001_ajob "
			
		//Cria a conexão no Banco de Dados	
		ConectaBanco con = new ConectaBanco();
		
		//lista para guardar as rotinas
		 ArrayList<dados> listDados = new ArrayList<dados>();
			
		try {
			
		      //Efetua o select no banco
			ResultSet consulta = con.executeQuery(sql);
           
			//Percorre as linhas com os resultados
		      while(consulta.next()) {
			   
			   //chama a classe com os dados da tabela
			    dados Dados = new dados();
			   
			    //Preenche a lista
			        Dados.setOrder_id(consulta.getString("order_id"));	
				Dados.setJob_name(consulta.getString("job_name"));
				Dados.setOdate(consulta.getString("odate"));
				Dados.setStart_time(consulta.getString("start_time"));
				Dados.setEnd_time(consulta.getString("end_time"));
				listDados.add(Dados);
		    }
  
		   
		   } catch (SQLException e) {
     		       e.printStackTrace();
	   }
           }
 }

Agora a duvida, como eu passo este arraylist para um outro metodo, para que assim eu possa inseri-lo no banco ?

Obrigado

Você declara seu método assim:

static List<dados> lista(String odateMov){
}

e no final do método você retorna a lista, assim:

static List<dados> lista(String odateMov){
   try{
   }catch(SQLException e){
       e.printStackTrace()
   }

   return listDados;
}

Obrigado mais uma vez rrmendes08.

depois do retorno, penso em passar esta lista em outro metodo para nele sim, inserir os dados no banco, tipo

static List inserirDados(Listlista){
}

é mais ou menos isso ?

Sim, o caminho é esse.

Eu fiz desta forma:

Primeiro método:

static List lista(String odateMov) {

   } catch (SQLException e) {
     		       e.printStackTrace();
 	   }
	//retorna a lista com os dados
	return listDados;

}

segundo metodo:

static void inserirDados(List lista){

		System.out.println(lista.toString());

}

e a MAIN:

public static void main(String[] args){
lista(“170705”);
inserirDados(lista); -> aqui da erro pois nao sei como passar o retorno do primeiro metodo

	}

Alguém poderia dar uma força ai?

como posso passar como parâmetro o retorno de uma lista de um método 1 para o método 2?

Ex:

static List lista(String odateMov) {
return list
}

static void inserirDados(List lista){
//imprime os dados da lista retornada.
System.out.println(lista.toString());
}

Não sei se é assim.

public static void main(String[] args){
lista(“170705”);
inserirDados(null) -> aqui eu insiro o retorno da lista, mas como eu faço ?

	}

Bom, consegui resolver o que eu queria.
até simples por sinal, agora preencho uma lista e no outro método eu trabalho com o retorno desta lista.

public class Teste {
public static void main(String[] args) throws Exception {

                           List<String> myList;
                          
                           myList = geraLista();
                          
                           processaLista(myList);
                                                          
            }

           
            private static List<String> geraLista(){
                           List<String> lista = new ArrayList<String>();
                           lista.add("123");
                           return lista;
            }             
           
           
            private void processaLista(List<String> lista){
                        System.out.println(lista.get(0));
            }

}