segunda-feira, 17 de novembro de 2008

ADF BC: Como inativar um registro ao invés de deletar

Olá novamente pessoal!

Hoje vamos fazer um rápido HOW-TO baseado em um requisito bastante comum. Por várias vezes, os clientes solicitam sistemas que não permitem a deleção de registros, para fins de histórico. Ao invés disso, cria-se na tabela um campo STATUS, que pode levar um flag ATIVO (por exemplo, 'A') ou INATIVO ('I'). Sabemos que o BC tem uma ação padrão chamada "Delete" que remove o registro do RowSet do View Object e, ao efetuar commit(), emite uma instrução DELETE ao banco de dados. E agora?
Para solucionar este problema, vamos utilizar a orientação a objetos do Java e estender a implementação da Entidade, sobrescrevendo os métodos responsáveis pela remoção e pela execução do DML. Dividiremos essa tarefa em duas partes:

PARTE 1: COMO ALTERAR O STATUS DO REGISTRO AO INVÉS DE REMOVER?
Para alcançar este primeiro objetivo, sobrescrevemos o método remove() da classe de implementação da entidade. Por exemplo, supondo que nossa entidade chame EmployeeEO e que existe um campo chamado STATUS dentro dessa entidade, teremos uma classe chamada EmployeeEOImpl onde iremos criar o seguinte método, sobrescrevendo da superclasse:


public void remove() {
// Chamada nova: setar o valor do status para 'I'
this.setStatus("I");

// Chamada original, comentada
// super.remove();
}


Com isso, ao invés de remover a linha do RowSet, ele irá somente alterar o status para "I". Porém, imaginem que precisemos manter a chamada de super.remove() no método para que, ao inativar o registro, ele suma da tela do usuário. Se isso for verdade, temos de achar alguma maneira de dizer ao BC que não é necessário um DELETE, mas sim um UPDATE. Aí vem a parte 2...

PARTE 2: ALTERANDO A LÓGICA DE DML DO ENTITY OBJECT
Na mesma classe de implementação da entidade, temos um método chamado doDML(int operation, TransactionEvent e). Este método é responsável por disparar os comandos DML no banco de dados, portanto vamos desenvolver um "gancho" que intercepta essa chamada e altera a operação desejada de DELETE para UPDATE, sobrescrevendo o método como abaixo:

public void doDML(int operation, TransactionEvent e) {
//O parâmetro "operation" indica a operação desejada
//Pode ser DML_UPDATE, DML_DELETE, DML_INSERT...
//A nossa ação é verificar se é um DML_DELETE, e se for, trocar para DML_UPDATE
if (operation == DML_DELETE) {
operation = DML_UPDATE;
}

// Ao chamar a superclasse, vai "enganá-la", emitindo um UPDATE!
super.doDML(operation, e);
}


Com isso, você pode usar a operação "Delete" do application module normalmente, que a entidade irá se comportar da maneira desejada. Pode-se inclusive chamar row.remove() em uma linha do View Object programaticamente que o comportamento está garantido.

Bom ADF para vocês! Até Mais!

Nenhum comentário: