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;
}
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.
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:
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.
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.
[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…
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.
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.
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?
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:
/** 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.
/** 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.