método synchronized

6 respostas
maresp

Verificando o log da minha aplicação web percebí que estão ocorrendo tentativas de inserção de registro no meu banco de dados com chave duplicada. Atualmente tento inibir isso através de um método synchronized que obtem um número sequencial em uma tabela que controla a sequencia. Achei que isso seria suficiente, mas não está sendo. Alguém conseque identificar onde que está vazando o problema?

public synchronized int pkGenerator(String sequencia) throws FileNotFoundException, IOException, SQLException {
		String sql = getProp(queryFile,"sequencia.update");
		PreparedStatement pSt = conn.prepareStatement(sql);
		pSt.setString(1,sequencia);
		/* cria uma sequencia caso ela não exista
		 * com o valor inicial 1
		 */
		if( pSt.executeUpdate() == 0 ) {
			sql = getProp(queryFile,"sequencia.insert");
			pSt = conn.prepareStatement(sql);
			pSt.setString(1,sequencia);
			pSt.setInt(2,1);
			pSt.executeUpdate();
		}
		
		sql = getProp(queryFile,"sequencia.select");
		pSt = conn.prepareStatement(sql);
		pSt.setString(1,sequencia);
		ResultSet rs = pSt.executeQuery();
		int codSeq = 0;
		while(rs.next()) {
			codSeq = rs.getInt(1);
		}
		pSt.close();
		rs.close();
		return codSeq;
	}

neste próximo método eu faço a inserção do registro e é onde eu utilizo o método anterior:

public void inserirResposta(Avaliacao aval, Grupo grupo, Questao questao, Disciplina dscpl, Aluno aluno)
		throws FileNotFoundException, IOException, SQLException {
		/* obter chave - sel max(cd_seq)+1 */
		int codSeq = new Integer(0);
		codSeq = pkGenerator(aval.getNomeTabela());
		}
		conn.setAutoCommit(false);
		String sql = "INSERT INTO " +
					 aval.getNomeTabela() +
					 "(cd_seq,cd_grupo,cd_qst,cd_altrn,cd_acad_seq,cd_dscpl,cd_prof,data_res) " +
					 "VALUES (" + codSeq + "," +
					 grupo.getCodigo() + "," +
					 questao.getCodigo() + "," +
					 dscpl.professor.getAvalOption() + "," +
					 aluno.getId() + "," +
					 dscpl.getId() + "," +
					 dscpl.professor.getId() + "," +
					 "now())";
		PreparedStatement pSt = conn.prepareStatement(sql);
		pSt.executeUpdate();
		conn.setAutoCommit(true);
		pSt.close();
	}

6 Respostas

louds

Voce tem mais de 1 instancia do Objeto que tem o método synchronized?

maresp

tenho… como eu disse a aplicação é web e estou utilizando sessões, o que me dá várias instâncias deste objeto.

louds

Bom, voce precisaria sincronizar globalmente o acesso a esse método…

maresp

ou seja, teria que fazer a sinchronização onde todos as instâncias do objeto fazem a chamada ao método… acho que é isso né…?

louds

Sim
voce pode fazer de uma forma bem simples:

class X {
  public int nextKey() {
    synchronized(X.class) {
  
     }
  }
}
maresp

Então...

sincronização no nível de classe:
class X { 
  public int nextKey() { 
    synchronized(X.class) { 
  
    } 
  } 
}
sincronização no nível de objeto:
class X { 
  public int nextKey() { 
    synchronized(this) { 
  
    } 
  } 
}

tá certo?

Criado 5 de novembro de 2003
Ultima resposta 5 de nov. de 2003
Respostas 6
Participantes 2