Problema com implementação de classes

Olá pessoal!

Antes de mais nada, não poderia deixar de mensionar a grande ajuda que vcs aqui do fórum tem me dado. Obrigado mesmo.

Mas agora tenho uma outra dúvida… Estava estudando UML e comecei a desenvolver um pequeno sistema para apreder melho Java e UML. No meu sistema eu tenho uma classe abstrata chamada PESSOA. De PESSOA eu crio as outras classes que representam as entidades do meu sistema, como, por exemplo, PESSOAFISICA. Estou dividindo tudo em modelos e DAOS. Ficou assim:

public class Pessoa {
    
    /** Creates a new instance of Pessoa */
    public Pessoa() {
    }
    
    public void setCodigo(Integer Codigo) {
        this.codigo = Codigo;
    }
    
    public void setNome(String Nome) {
        this.nome = Nome;
    }
    
    public void setCadastro(Date Cadastro) {
        this.cadastro = Cadastro;
    }
    
     public Integer getCodigo() {
        return this.codigo;
    }
    
    public String getNome() {
        return this.nome;
    }
    
    public Date getCadastro() {
        return this.cadastro;
    }
    
    private Integer codigo;
    private String nome;
    private Date cadastro;
    
}

public class PessoaDAO {
    
    /** Creates a new instance of PessoaDAO */
    public PessoaDAO() {
    }
    
    public Pessoa getPessoa() {
        return this.pessoa;
    }
    
    public void setPessoa(Pessoa pessoa) {
        this.pessoa = pessoa;
    }
    
    public void inserir() {
        //... Código para inserir a pessoa no banco de dados.
    }
    
    public void alterar() {
        //... Código para alterar a pessoa no banco de dados.
    }
    
    public void apagar() {
        //... Código para apagar a pessoa do banco de dados.
    }
    
    private Pessoa pessoa;
}

public class PessoaFisica extends Pessoa {
    
    /** Creates a new instance of PessoaFisica */
    public PessoaFisica() {
    }
    
    public void setCPF(String CPF) {
        this.cpf = CPF;
    }
    
    public String getCPF() {
        return this.cpf;
    }
    
    private String cpf;
    
}

public class PessoaFisicaDAO extends PessoaDAO {
    
    /** Creates a new instance of PessoaFisicaDAO */
    public PessoaFisicaDAO() {
        super();
    }
    
    public void setPessoaFisica(PessoaFisica pessoa) {
        this.pessoa = pessoa;
    }
    
    public PessoaFisica getPesoaFisica() {
        return this.pessoa;
    }
    
    public void inserir() {
        super.inserir();
        //... Código para inserir no banco de dados.
    }
    
    public void alterar() {
        super.alterar();
        //... Código para alterar.
    }
    
    public void apagar() {
        //Código para apagar.
        super.apagar();
    }
    
    private PessoaFisica pessoa;
    
}

Será que essa é uma boa prática?

Outra coisa… Como faço para controlar a transação com estemétodo. Porque da forma como está eu estou correndo o risco de inserir uma pessoa no banco de dados, mas não inserir uma pessoa física. Se der um problema na inserção da pessoa física no banco, vou ter a pessoa cadastrada, mas não vou ter uma pessoa física no banco de dados.

Como controlo isso?

Utilizar encpasulamento e separar as classes de acesso ao banco (DAO) é uma boa prática sim. Porém, se analisarmos seu código veremos alguns problemas:

  1. Você cria uma classe abstrata Pessoa, porém não a declara abstrata e ainda se propoem a salvar os dados de um objeto pessoa no Banco. Isto vai contra o principio de utilizar classes abstratas. Primeiro porque você não pode instanciá-las como você faz no seu programa, e outra que, ao utilizar um tipo genérico como Pessoa para criar objetos mais completos como PessoaFísica e PessoaJurídica, você só deve se preocupar em utilizar apenas as subclasses de Pessoa, porém se você quiser utilizar a classe Pessoa como objeto, é melhor criar uma classe concreta mesmo, e não abstrata.

  2. Para controlar a transação, eu por exemplo, crio um método simples que me retorna true or false se o dado for encontrado no banco ou também crio um método para me retornar algum dado que não pode ser repetido, por exemplo, criar um método pessoaCadastrada(String nome) e cpfCadastrado(String documento), enfim, faça com que antes de inserir dados, seu objeto passe por essas verificações e aí sim faça o INSERT no banco.

Espero ter ajudado…

[quote=“virtus”]Outra coisa… Como faço para controlar a transação com estemétodo. Porque da forma como está eu estou correndo o risco de inserir uma pessoa no banco de dados, mas não inserir uma pessoa física. Se der um problema na inserção da pessoa física no banco, vou ter a pessoa cadastrada, mas não vou ter uma pessoa física no banco de dados.

Como controlo isso?[/quote]

Você teria que passar a conexão do método inserir Pessoa para o método inserir Pessoa Física, caso ocorra alguma exceção você dá um rollback nessa conexão…

Eu faço assim:

[code]public static int incluirPessoa(Pessoa p, PessoaFisica pf) {

Connection conn = null;
… // recebe a conexão do pool

… // inserindo pessoa

try {

incluirPessoaFisica(pf, conn)

}
catch(Exception e) {
conn.rollback();
throw new Exception("Erro ao Inserir Pessoa Física: "+ e.getMessage());

}

}[/code]

Não sei se é a melhor maneira… mas sei que existe uma API específica para controle de transações: JTA

É interessante que você crie uma classe que contenha os métodos que realizem o controle das transações…

:wink:

Muito legal!

Acho que vou fazer o seguinte…

  1. Vou usar a classe PESSOA como concreta e não como abstrata. Assim quando tiver que criar uma entidade nova, não vou precisar criar a implementação para os dados relativos a PESSOA. Isso deve ficar melhor ainda quando tiver que estender classes mais avançadas, como PESSOAFISICA -> ADVOGADO ou PESSOAJURIDICA->FORNECEDOR.

  2. Gostei da idéia de passar a conexão para dentro da classe que insere os modelos no banco dedados. Eu posso passar a conexão para a classe PESSOAFÍSICA e a classe PESSOA usar a mesma conexão por herança. Cara isso deve ficar irado para classes que controlam a conexão com bancos de dados diferentes… posso usar uma classe abstrata e o DAO não precisar conhecer de qual banco é a conexão.

  3. Parece ser bem legal criar uma classe para controlar a trnasação da conexão com o banco de dados. Acho que diminuirá co código na classe de conexão.

Vou modificar o código postado e colocar aqui pra vcs darem uma olhada, ok?

Uma das vantagens de utilizar JTA é:

Enquanto o JDBC é limitada apenas a uma conexão, uma conexão JTA pode ter múltiplos participantes…

Sim… se você não utilizar JTA essa pode ser uma boa opção!!

Você teria os seguintes métodos nessa classe:
[list][:bfde7a46ee]begin();
[
:bfde7a46ee]commit();
[*:bfde7a46ee]rollback();[/list]
E por aí vai… :mrgreen:

Olha o que eu fiz… :razz:

[code]
public class PessoaDAO {

/** Creates a new instance of PessoaDAO */
public PessoaDAO(Connection cn, Transaction tr) {
    this.cn = cn;
    this.tr = tr;
}

public void inserir() throws Exception {
    // insere a pessoa no banco de dados
}

public Connection getConnection() {
    return this.cn;
}

public Transaction getTransaction() {
    return this.tr;
}

private Pessoa pessoa;
private Connection cn;
private Transaction tr;

}

public class PessoaFisicaDao extends Pessoa {

/** Creates a new instance of PessoaFisicaDao */
public PessoaFisicaDao(Connection cn, Transaction tr) {
    super(cn, tr);
}

public void inserir() {
        super.inserir();
        //Insere a pessoafisica no banco de dados
}

}[/code]

Assim eu posso controlar a transação de uma forma externa ( interna também ) à classe Pessoa e suas Filhas. Além disso, não vou precisar implementar a abertura e fechamento de conexão ( e das transações ) nas filhas da classe Pessoa.

O que acham? É uma boa idéia?

[quote=“virtus”]Olha o que eu fiz… :razz:

[code]
public class PessoaDAO {

/** Creates a new instance of PessoaDAO */
public PessoaDAO(Connection cn, Transaction tr) {
    this.cn = cn;
    this.tr = tr;
}

public void inserir() throws Exception {
    // insere a pessoa no banco de dados
}

public Connection getConnection() {
    return this.cn;
}

public Transaction getTransaction() {
    return this.tr;
}

private Pessoa pessoa;
private Connection cn;
private Transaction tr;

}

public class PessoaFisicaDao extends Pessoa {

/** Creates a new instance of PessoaFisicaDao */
public PessoaFisicaDao(Connection cn, Transaction tr) {
    super(cn, tr);
}

public void inserir() {
        super.inserir();
        //Insere a pessoafisica no banco de dados
}

}[/code]

Assim eu posso controlar a transação de uma forma externa ( interna também ) à classe Pessoa e suas Filhas. Além disso, não vou precisar implementar a abertura e fechamento de conexão ( e das transações ) nas filhas da classe Pessoa.

O que acham? É uma boa idéia?[/quote]

Pessoa ou PessoaDAO ???

Como você criou a classe Transaction ??

:wink:

PessoaDAO e PessoaFisicaDAO.

Na transação eu tenho uma referencia para a conexão.

public class Transaction {

public Transaction(Connection cn) {
    this.cn = cn;
}

public void commit() {
   this.cn.commit();
}

public void rollback() {
   this.cn.rollback()
}

private Connection cn;
}

Pensando melhor… eu poderia passar somente a transação para as classes DAOs, e assim, poderia ter acesso a conexão pela classe Transaction.

Consegui explicar melhor?

Se ainda tiver ficado confuso, eu psso postar o código completo pra vcs darem uma olhada. ok? :grin:

[quote=“virtus”]PessoaDAO e PessoaFisicaDAO.

Na transação eu tenho uma referencia para a conexão.

public class Transaction {

public Transaction(Connection cn) {
    this.cn = cn;
}

public void commit() {
   this.cn.commit();
}

public void rollback() {
   this.cn.rollback()
}

private Connection cn;
}

Pensando melhor… eu poderia passar somente a transação para as classes DAOs, e assim, poderia ter acesso a conexão pela classe Transaction.

Consegui explicar melhor?[/quote]

Sim…

Também acho que seria melhor deixar a transação somente nos DAOs.

:wink:

Bem pessoal…

Obrigado mais uma vez.

T+ galera!!!