E aí pessoal, tudo bem? Tô ficando doido e não aguento mais ficar doido sozinho, por isso vim recorrer a vocês…
Tenho um código em um JFrame que calcula o número de taxas emitidas, as pagas e não pagas por categoria (Enfermeiro, Técnico e Auxiliar). As duas tabelas consultadas são profisisonais (92.000 registros) e movboletos (2.100.000).
Para armazenar esta listagem, utilizei ArrayList, Para conexão com o banco MySQL usei JDBC com o drive mysql-connector-java-5.1.34-bin.jar
O problema é que para executar a query está demorando 10 segundos porém para retornar o resultado “na tela”, aproximadamente 25 minutos (impossível esperar que o usuário aguente tamanha espera).
Como não consigo imaginar a SQL de outra forma, nem conheço à fundo a linguagem em Java (é meu primeiro programa após 5 anos de PHP estruturado), recorro a vocês para entender e resolver o porquê de tanta demora. O problema é com o ArrayList, minha programação ou a SQL?
Segue abaixo as classes utilizadas:
1 - Classe que gera o ArrayList com os boletos:
public class BoletoDAO {
private Connection connection;
public BoletoDAO(){
this.connection = new ConnectionFactory().getConnection();
}
public ArrayList<Boleto> listaInadimplentes(int ano){
String sql = "SELECT M.CDCATEGORIA, M.NUINSCPROF, M.CDTIPO, M.CDTAXA, M.NUPARCELA, M.CDSTATUSP FROM MOVBOLETOS M "
+ "WHERE "
+ "M.ANO = "+ano+" AND ( "
+ "M.CDCATEGORIA like '01' OR M.CDCATEGORIA like '03' OR M.CDCATEGORIA like '04'"
+ ") AND "
+ "M.CDTIPO like '04' AND "
+ "M.NUINSCPROF = ("
+ "SELECT P.NUINSCPROF FROM PROFISSIONAIS P "
+ "WHERE "
+ "M.CDCATEGORIA = P.CDCATEGORIA AND "
+ "M.CDTIPO = P.CDTIPO AND "
+ "M.CDSUBTIPO = P.CDSUBTIPO AND "
+ "M.NUINSCPROF = P.NUINSCPROF AND "
+ "P.CDSITUACAO = 1 "
+ ") "
+ "ORDER BY "
+ "M.CDCATEGORIA, M.NUINSCPROF, M.CDTIPO, M.CDTAXA, M.NUPARCELA ASC";
try{
//prepara a SQL para ser executada
PreparedStatement ps = this.connection.prepareStatement(sql);
//executa a query
ResultSet rs = ps.executeQuery();
//cria uma List que ira armazenar os profissionais
ArrayList<Boleto> boletos = new ArrayList<Boleto>();
//enquanto houver registros, faca:
while(rs.next()){
Boleto boleto = new Boleto();
boleto.setChave(rs.getString("NUINSCPROF")+"-"+rs.getString("CDCATEGORIA")+"-"+rs.getString("CDTIPO")+"-"+rs.getInt("CDTAXA"));
boleto.setNuInscProf(rs.getString("NUINSCPROF"));
boleto.setCdCategoria(rs.getString("CDCATEGORIA"));
boleto.setCdTipo(rs.getString("CDTIPO"));
boleto.setCdTaxa(rs.getInt("CDTAXA"));
boleto.setNuParcela(rs.getInt("NUPARCELA"));
boleto.setCdStatusP(rs.getString("CDSTATUSP"));
//adicione este boleto encontrado na lista de boletos
boletos.add(boleto);
}
//finaliza o PreparedStatement
ps.close();
//finaliza o ResultSet
rs.close();
//retorna a LIST para quem chamar a funcao "inadimplentes"
return boletos;
}catch(SQLException e){
throw new RuntimeException(e);
}
}
}
O código acima demora 10 segundos para rodar no código JAVA em localhost, sendo que via phpmyadmin o tempo de execução da SQL é de 6 segundos.
2 - método initComponents da JFrame que exibe na tela o número de registros:
public void initComponentsTrue(){
..
..
..
//abaixo fazemos a lógica dos inadimplentes:
//variaveis Globais para calculo dos inadimplentes:
int enfNum = 0;
int enfPago = 0;
int enfNaoPago = 0;
int tecNum = 0;
int tecPago = 0;
int tecNaoPago = 0;
int auxNum = 0;
int auxPago = 0;
int auxNaoPago = 0;
int totNum = 0;
int totPago = 0;
int totNaoPago = 0;
//inicializa o DAO correspondente
BoletoDAO dao = new BoletoDAO();
//armazena na variavel boletos de 2014.
ArrayList<Boleto> boletos = dao.listaInadimplentes(2014);
String chaveAnterior = "";
for(Boleto bol : boletos){
String chaveFor = bol.getNuInscProf()+"-"+bol.getCdCategoria()+"-"+bol.getCdTipo()+"-"+bol.getCdTaxa();
//se a chaveAnterior for diferente da chaveFor, é uma nova chave, portanto:
if(!chaveAnterior.equals(chaveFor)){
//cria variáveis para controlar o tipo de profissional
boolean enf = false;
boolean tec = false;
boolean aux = false;
//verifica se a categoria é 01 (enfermeiro)
if(bol.getCdCategoria().equals("01")){
enf=true;
++enfNum;
}
//verifica se a categoria é 03 (técnico)
if(bol.getCdCategoria().equals("03")){
tec=true;
++tecNum;
}
//verifica se a categoria é 04 (auxiliar)
if(bol.getCdCategoria().equals("04")){
aux=true;
++auxNum;
}
ArrayList<Boleto> boletosChave = new ArrayList<>();
boletosChave = bol.getChavesIguais(chaveFor,boletos);
for(Boleto b : boletosChave){
//variaveis de registro para os if's
int cdTaxa = b.getCdTaxa();
int nuParcela = b.getNuParcela();
String cdStatusP = b.getCdStatusP();
if(cdTaxa == 0 && nuParcela == 0 && cdStatusP != null){
//cria variável para controlar se as parcelas foram pagas
boolean todasParcelasPagas = true;
//cria novo array que será varrido para ver se há alguma parcela não paga dessa chave
ArrayList<Boleto> varreBoletos = new ArrayList<>();
varreBoletos = b.getChavesIguais(chaveFor,boletos);
//para cada boleto dentro desse ArrayList
for(Boleto outrosBoletos : varreBoletos){
//verifica se algum tem o CDSTATUSP == NULL, pois aí não foram todos pagos
if(outrosBoletos.getCdStatusP() == null){
todasParcelasPagas = false;
}
}
//se todas parcelas foram pagas, soma como mais uma taxa paga, se não, como não paga
if(todasParcelasPagas){
if(enf) ++enfPago;
if(tec) ++tecPago;
if(aux) ++auxPago;
}else{
if(enf) ++enfNaoPago;
if(tec) ++tecNaoPago;
if(aux) ++auxNaoPago;
}
//sai desse for, passando pra próxima chave
break;
}
//se há somente uma parcela única (cdtaxa=0), não paga e nenhuma outra parcela adicionamos como mais um registro não pago
if(cdTaxa==0 && nuParcela==0 && cdStatusP==null){
//se o núm. de registros dessa chave for < 2,
//quer dizer que só há um único registro,portanto, some mais um não pago
if(boletosChave.size()<2){
if(enf) ++enfNaoPago;
if(tec) ++tecNaoPago;
if(aux) ++auxNaoPago;
//sai desse for, passando pra próxima chave
break;
}
}
//se anuidade (taxa=0) e parcela normal (numparcela!=0)
if(cdTaxa == 0 && nuParcela != 0){
//cria variável para controlar se as parcelas foram pagas
boolean todasParcelasPagas = true;
//cria novo array que será varrido para ver se há alguma parcela não paga dessa chave
ArrayList<Boleto> varreBoletos = new ArrayList<>();
varreBoletos = b.getChavesIguais(chaveFor,boletos);
//para cada boleto dentro desse ArrayList
for(Boleto outrosBoletos : varreBoletos){
//se nuparcela!=0 (parcela normal) e cdstatusp==NULL (não paga)
if(outrosBoletos.getNuParcela() != 0 && outrosBoletos.getCdStatusP() == null){
todasParcelasPagas = false;
}
}
//se todas parcelas foram pagas, soma como mais uma taxa paga, se não, como não paga
if(todasParcelasPagas){
if(enf) ++enfPago;
if(tec) ++tecPago;
if(aux) ++auxPago;
}else{
if(enf) ++enfNaoPago;
if(tec) ++tecNaoPago;
if(aux) ++auxNaoPago;
}
//sai desse for, passando pra próxima chave
break;
}
//qualquer taxa em que cdtaxa!=0 não é preciso nenhuma outra verificação,
//só se verifica se o StatusP é == OU != de NULL
if(cdTaxa != 0){
//se cdStatusP == NULL, esta taxa não foi paga
if(cdStatusP==null){
if(enf) ++enfNaoPago;
if(tec) ++tecNaoPago;
if(aux) ++auxNaoPago;
}else{
if(enf) ++enfPago;
if(tec) ++tecPago;
if(aux) ++auxPago;
}
//sai desse for, passando pra próxima chave
break;
}
}//fim do for(Boleto b : boletosChave){
}//fim do if(!chaveAnterior.equals(chaveFor)){
//ao final, seta que a chaveAnterior vira a chaveFor, para comparação com o próximo registro
chaveAnterior = chaveFor;
}
totNum = enfNum + tecNum + auxNum;
totPago = enfPago + tecPago + auxPago;
totNaoPago = enfNaoPago + tecNaoPago + auxNaoPago;
//fim da lógica para cálculo dos Inadimplentes.
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{"Enfermeiro", enfNum, enfPago, enfNaoPago},
{"Técnico", tecNum, tecPago, tecNaoPago},
{"Auxiliar", auxNum, auxPago, auxNaoPago},
{"Total", totNum, totPago, totNaoPago}
},
new String [] {
"Categoria", "Emitidas", "Pagas", "Não Pagas"
}
)
...
...
...
}
Então… eu não sei mais o que fazer, será que utilizar matriz ao invés do ArrayList é melhor? O que devo fazer? Me ajudem hehehe
Um abraço! Obrigado![/b]