Persistir atributos privados

Gostaria de uma ideia de como persistir atributos privados de uma classe sem expo-los para o ambiente externo.
ex:

class Funcionario
{
   private int id;
   public int getId() {}
   
}

Não tem setId, pois esse campo é atribuido internamente.
O ambiente externo não pode atribuir valor para ele, somente consultar.
Como eu faria para recuperar ou persistir esse campo em um DAO e no Hibernate ?

Hibernate trabalha sem getters e setters:
http://wrschneider.blogspot.com/2005/01/avoiding-anemic-domain-models-with.html
Legal né :smiley:

Mesmo que não use Hibernate, pode fazer alguma coisa com reflection. E não é a mesma coisa que usar setters. Persistência é um problema que precisa ser resolvido, mas não é por causa dele que você precisa ferrar o resto hehe :smiley:

Mas nestes casos se a segurança do JVM não permitir que os atributos sejam acessados ?
Tem alguma coisa nesse sentindo Security…Alguma coisa que eu não lembro.

Tem sim!

Se por algum motivo o ambiente de produção tem essa restrição, você pode usar um desses:
http://jakarta.apache.org/bcel/index.html
http://cglib.sourceforge.net

Ou implementar você mesmo algo semelhante, o que não é tão dificil assim.

Aliás, esqueça todo o resto e use Hibernate hehe

“Ah, é mais fácil ter getters e setters”. Você que sabe, oras :smiley:

Se você criar um private setter, o Hibernate consegue persistir sem problemas.

Mas em uma DAO ?
se eu extendesse o objeto a partir de uma classe com métodos para trabalhar a persistencia
ex:


class Funcionario extends Persistente
{
   private int id;

  protected void persistir(Dados dados)
  {
     dados.setInt("ID",geraId());
  }


  protected void recuperar(Dados dados)
  {
     id = dados.getInt("ID");
  }

}

Isso fica legal ?

Isso tem nome já :smiley:
http://www.martinfowler.com/eaaCatalog/activeRecord.html

Novamente, não sou nenhum expert em patterns, mas ActiveRecord + IoC cheira bem para mim.

Voce pode usar métodos e atributos package protected e colocar classes auxiliares de persistencia no mesmo pacote dos teus objetos de domínio.

Essa ideia é muito boa.
Fica a mais elegante e menos gambiarrenta.

Mas eu poderia ter vários DAOs para diferentes tipos de dados.
Como eu lidaria com isso ?
Colocaria todos os DAOs dentro do mesmo package da classes de negócio ?

Mas o caminho é por aí mesmo…

Ou você pode usar um pouco de mágica com reflection, o ruim é que você perde a tipagem forte do java.

Tive uma ideia vejam se fica tosca


teste.funcionario

class FuncionarioDAO
{
  protected final setId(Funcionario func,int id)
  {
     func.setId(id);
  }
}

class Funcionario
{
   private int id;
   setId(int id) {}
   public getId() {} 	
}


teste.data


class DAOFactory
{
  FuncionarioDAO getFuncionarioDAO()
  {
     
  }
}

class FuncionarioHibernateDAO extends teste.funcionario.FuncionarioDAO
{
  // nao precisa fazer nada de diferente
}

class FuncionarioSqlDAO extends teste.funcionario.FuncionarioDAO
{
  public Funcionario consultar()
  {
     Funcionario f = new Funcionario();
     setId(f,1);
  }   
}

Nessas horas é que eu vejo que é melhor deixar dados e operaçoes tudo na mesma classe.
Se a classe Funcionario se persistisse esse problema não ocorreria.

Mas como criar uma classe de negócios que se auto-persista e ainda permita diversos mecanismos de persistencia ?

[quote=jprogrammer]Nessas horas é que eu vejo que é melhor deixar dados e operaçoes tudo na mesma classe.
Se a classe Funcionario se persistisse esse problema não ocorreria.

Mas como criar uma classe de negócios que se auto-persista e ainda permita diversos mecanismos de persistencia ?

[/quote]

Delegates, Strategy, State.

Exemplifique

interface FuncionarioPersistenceStrategy {
   void save(Funcionario f);
}

class FuncionarioHibernate implements FuncionarioPersistenceStrategy {
  void save(Funcionario f) {
    session.save(f);
  }
}

class FuncionarioJDBC implements FuncionarioPersistenceStrategy {
  void save(Funcionario f) {
    insert into funcionario(nome) values ('oi');
  }
}

class Functionario {
  FuncionarioPersistenceStrategy strategy;


  public void save() {
    strategy.save(this);
  }
}

O livro do GOF explica State e Strategy muito bem, leitura recomendada.

Louds,

Me diz uma coisa, essa classe FuncionarioPersistenceStrategy tu instanciaria dentro da propria classe Funcionario ou usaria do tipo de DI pra isso?

Ps.: Eu ando fazendo isso num sistema aqui e nao tinha me dado conta do padrao.

]['s

Fabio, fica a seu gosto e necessidade :wink:

Normalmente, eu pelo menos, tenho uma classe enumerando as implementações mais freqüêntes e uns helpers de uma Strategy.

[quote=louds]...

O livro do GOF explica State e Strategy muito bem, leitura recomendada.[/quote]

Essa estrategia eh legal, pois apenas as camadas adjacentes comunicam-se entre si, mas ainda assim as classes de persistencia precisam obter/armazenar dados na classe de modelo. E ai vem o problema de ter gets/sets apenas para isso. Poderiamos fazer as classes de persistencia extender do modelo ou vice-versa, mas nao acho isso muito elegante.

Deparei-me com essa situacao essa semana: estou criando um modelo sem gets/sets, MAS na hora de puxar os dados da fonte tem essa encrenca. Nao posso utilizar Hibernate.

Ou seja - a solucao mais viavel parece ser criar gets/sets com acesso default/package e deixar as classes de persistencia e modelo no mesmo pacote. Voces veem alguma outra solucao?

A questao pode ser resumida em (IMHO): preciso dar acesso aos campos internos da classe, mas apenas para um caso especifico e excepcional (persistencia).

Marcio Kuchma

Gosto de usar uma factory simples e, pra ganhar flexibilidade, mover os nomes das implementacoes para um properties externo (de preferencia fora do pacote principal, pra nao precisar redistribuir/fazer redeploy quando precisamos mudar alguma coisa).

Em projetos sem limitacoes e que voce pode fazer as coisas sem medo de ser feliz, IoC pode ser uma boa (evita esse trampinho tosco de instanciar as classes dinamicamente e tal, apesar de ser coisa que se faz apenas uma vez).

Marcio Kuchma

[quote=kuchma]…MAS na hora de puxar os dados da fonte tem essa encrenca. Nao posso utilizar Hibernate.
[/quote]
Hibernate não precisa de getters e setters.