Anotações de hibernação - Qual é o melhor acesso a campos ou propriedades?

Respostas:

33

Prefiro acessadores, pois posso adicionar alguma lógica comercial aos meus acessadores sempre que necessário. Aqui está um exemplo:

@Entity
public class Person {

  @Column("nickName")
  public String getNickName(){
     if(this.name != null) return generateFunnyNick(this.name);
     else return "John Doe";
  }
}

Além disso, se você lançar outras bibliotecas na mistura (como algumas bibliotecas de conversão JSON ou BeanMapper ou Dozer ou outra biblioteca de mapeamento / clonagem de beans com base nas propriedades getter / setter), você terá a garantia de que a biblioteca está sincronizada com a persistência gerente (ambos usam o getter / setter).

Miguel Ping
fonte
17
Observe que é sobre como o ORM acessa seus campos / propriedades e não o código do aplicativo. Com o acesso ao campo, seu método getNickName () funcionaria exatamente como o esperado. O mesmo não se aplica se você usar as 'propriedades' persistentes fora de getters / setters. É aí que você pode encontrar problemas com o acesso à propriedade e o carregamento lento. Então não, eu não concordo com esse argumento em geral. No entanto, a última vez que verifiquei o Hibernate teve problemas com o acesso a campos @Id.
Rob Bygrave
11
esta resposta não está relacionada à pergunta. Melhor resposta s por duffymo
22/09/12
9
não deve haver lógica comercial dentro dos acessadores. esse não é um comportamento óbvio.
iuriisusuk
Por que essa resposta está correta? Não é verdade que você pode mapear o campo e fornecê-lo da mesma maneira.
Lucke 16/01
246

Existem argumentos para ambos, mas a maioria deles decorre de certos requisitos do usuário "e se você precisar adicionar lógica para" ou "xxxx quebra o encapsulamento". No entanto, ninguém realmente comentou a teoria e deu um argumento devidamente fundamentado.

O que o Hibernate / JPA está realmente fazendo quando persiste em um objeto - bem, ele persiste no estado do objeto. Isso significa armazená-lo de uma maneira que possa ser facilmente reproduzido.

O que é encapsulamento? Encapsulamentos significa encapsular os dados (ou estado) com uma interface que o aplicativo / cliente pode usar para acessar os dados com segurança - mantendo-os consistentes e válidos.

Pense nisso como o MS Word. O MS Word mantém um modelo do documento na memória - os documentos STATE. Apresenta uma interface que o usuário pode usar para modificar o documento - um conjunto de botões, ferramentas, comandos de teclado etc. No entanto, quando você escolhe persistir (Salvar), o documento salva o estado interno, não o conjunto de teclas pressionadas e cliques do mouse usados ​​para gerá-lo.

Salvar o estado interno do objeto NÃO quebra o encapsulamento - caso contrário, você realmente não entende o que significa encapsulamento e por que ele existe. É exatamente como serialização de objetos.

Por esse motivo, na maioria dos casos, é apropriado persistir nos CAMPOS e não nos ACESSORES. Isso significa que um objeto pode ser recriado com precisão do banco de dados exatamente da maneira como foi armazenado. Ele não deve precisar de validação, porque isso foi feito no original quando foi criado e antes de ser armazenado no banco de dados (a menos que Deus não permita, você está armazenando dados inválidos no banco de dados !!!!). Da mesma forma, não deve ser necessário calcular valores, pois eles já foram calculados antes do armazenamento do objeto. O objeto deve ter a mesma aparência que antes de ser salvo. De fato, adicionando itens adicionais aos getters / setters, você aumenta o risco de recriar algo que não é uma cópia exata do original.

Obviamente, essa funcionalidade foi adicionada por um motivo. Pode haver alguns casos de uso válidos para persistir os acessadores; no entanto, eles geralmente são raros. Um exemplo pode ser que você deseja evitar a persistência de um valor calculado, embora faça a pergunta por que não o calcula sob demanda no getter do valor ou inicializa preguiçosamente no getter. Pessoalmente, não consigo pensar em nenhum bom caso de uso, e nenhuma das respostas aqui realmente fornece uma resposta "Engenharia de software".

Martin
fonte
9
A resposta da engenharia de software é: o uso de acessadores viola o DRY.
precisa saber é o seguinte
1
@ Martin Tenho uma pergunta de acompanhamento referente ao último parágrafo da sua resposta. Você escreveu "Um exemplo pode ser que você deseja evitar a persistência de um valor calculado". Como você pode evitar a persistência de um valor calculado tendo acesso baseado em propriedade? Sei que você está argumentando para não fazê-lo, mas não estou entendendo o ponto aqui. Você pode explicar, por favor?
21714 Geek
4
@ Geek Agora que eu li de volta, não tenho muita certeza. Faz dois anos que escrevi esta resposta. Eu acho que um exemplo melhor pode ser o local em que você está trabalhando com um banco de dados legado, e os dados são apresentados de uma maneira diferente do seu modelo de objeto - os acessadores podem fornecer um mapeamento entre os dois.
Martin
23
Um bom caso de uso para mapear acessadores é quando você precisa adicionar informações de mapeamento a subclasses de classes de entidades de terceiros que não estão vinculadas a nenhuma implementação de persistência. Como os campos são particulares nessas classes, você deve substituir os acessadores e adicionar anotações de mapeamento a eles. Outra opção seria usar o mapeamento XML, mas algumas coisas são muito difíceis de fazer lá. Portanto, se você deseja anotações e mapeia classes de terceiros, é necessário subclassificá-las e adicionar anotações nos acessadores.
Elnur Abdurrakhimov
5
@ElnurAbdurrakhimov lá vamos nós, um excelente exemplo. Obrigado.
Martin
79

Prefiro o acesso ao campo, porque dessa forma não sou obrigado a fornecer getter / setter para cada propriedade.

Uma pesquisa rápida via Google sugere que o acesso ao campo é a maioria (por exemplo, http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype ).

Acredito que o acesso ao campo é o idioma recomendado pelo Spring, mas não consigo encontrar uma referência para fazer backup disso.

Há uma pergunta relacionada ao SO que tentou medir o desempenho e chegou à conclusão de que "não há diferença".

duffymo
fonte
Se você não fornecer getter setter na entidade, em seguida, que é o uso desse campo ... você não pode usá-lo anwyhere na aplicação, becuase campos são privados
anshulkatta
1
Não está fornecendo um getter e setter para suas práticas ruins de campos ?, acho que meu comentário aqui nem sempre é correto, pois eu estava assumindo um campo público, embora pudesse obviamente ser um campo privado que nunca é acessado.
Mathijs Segers
3
@anshulkatta Acho que realmente devo responder às suas perguntas, pois é disso que se trata o encapsulamento. Idealmente, todos os seus campos devem ser privados e, se possível, não devem ter getters ou setters - esse é o melhor nível de encapsulamento que você pode esperar. Considere um verificador de senha. 2 campos privados passwordHash e failAttempts. Ambos podem ser privados sem getter ou setter. Eles são usados ​​pelo bool checkPassword (string password) que faz hash, verifica contra passwordHash e, em seguida, atualiza failAttempts e retorna um resultado. Não há necessidade de outro código para acessar esses dois campos.
Martin Martin
2
@anshulkatta deve-se notar que no OOP, getters e setters são um antipadrão, eles vêm da programação procedural, ter uma classe com eles quebra o princípio do encapsulamento e gera muito código padrão, ou seja, o mesmo tipo de código repetido várias vezes. Os objetos devem ser imutáveis, se for necessária a modificação de suas propriedades, isso deve ser feito através de um método que faça algo mais do que apenas retornar o valor da propriedade.
Uriel Arvizu
Não tão. "Anti-padrão", neste caso, é uma questão de opinião, não dogma. Com isso dito, o acesso ao campo ainda é o preferido. Uma idéia melhor é evitar completamente as soluções ORM. Aprenda a escrever SQL adequado.
Duffymo 27/05
38

Aqui está uma situação em que você PRECISA usar acessadores de propriedades. Imagine que você tenha uma classe abstrata GENERIC com muitas vantagens de implementação para herdar em 8 subclasses concretas:

public abstract class Foo<T extends Bar> {

    T oneThing;
    T anotherThing;

    // getters and setters ommited for brevity

    // Lots and lots of implementation regarding oneThing and anotherThing here
 }

Agora, exatamente como você deve anotar esta classe? A resposta é: VOCÊ NÃO PODE anotá-la com acesso a campos ou propriedades, porque não é possível especificar a entidade de destino neste momento. Você deve anotar as implementações concretas. Mas como as propriedades persistidas são declaradas nesta superclasse, você DEVE usar o acesso à propriedade nas subclasses.

O acesso ao campo não é uma opção em um aplicativo com superclasses genéricas abstratas.

HDave
fonte
2
touche. Eu não tinha pensado nisso. Aposto que o Hibernate lança algum sql louco para eles.
Joseph Lust
8
Esse problema parece mecanicamente difícil de resolver sem fazer anotações nas propriedades, mas nunca encontrei um caso em que precisasse de uma classe genérica abstrata com muita implementação que também desejasse persistir. Normalmente, crio uma hierarquia de classes para tornar meu objeto polimórfico (o que o torna um tipo genérico de quebras), e não apenas para reutilização de código. E "muita e muita implementação" geralmente viola o SRP de qualquer maneira; nesse caso, eu provavelmente o moveria para classes separadas. Existe um exemplo concreto que torne esse caso de uso mais óbvio?
Merlyn Morgan-Graham
O único exemplo concreto que tenho é o meu aplicativo, que não consigo descrever em um comentário de 500 caracteres ;-)
HDave
3
Você pode usar abstract T getOneThing(), e abstract void setOneThing(T thing), e usar o acesso ao campo.
Arturo Volpe
33

Costumo preferir e usar acessadores de propriedades:

  • Eu posso adicionar lógica se necessário (como mencionado na resposta aceita).
  • isso me permite ligar foo.getId() sem inicializar um proxy (importante ao usar o Hibernate, até que o HHH-3718 seja resolvido).

Recua:

  • isso torna o código menos legível, você precisa, por exemplo, procurar uma classe inteira para ver se há @Transientpor aí.
Pascal Thivent
fonte
mas se você usar um provedor JPA que não tenha "proxies", não terá esse problema, conhecido como "seu provedor JPA está impondo a você".
Neil Stockton
13

Isso realmente depende de um caso específico - ambas as opções estão disponíveis por um motivo. OMI resume-se a três casos:

  1. o setter possui alguma lógica que não deve ser executada no momento do carregamento de uma instância de um banco de dados; por exemplo, alguma validação de valor ocorre no setter, no entanto, os dados provenientes do db devem ser válidos (caso contrário, não chegariam lá (:); nesse caso, o acesso ao campo é mais apropriado;
  2. setter tem alguma lógica que sempre deve ser chamada, mesmo durante o carregamento de uma instância do db; por exemplo, a propriedade que está sendo inicializada é usada no cálculo de algum campo calculado (por exemplo, propriedade - uma quantia monetária, propriedade calculada - um total de várias propriedades monetárias da mesma instância); nesse caso, o acesso à propriedade é necessário.
  3. Nenhum dos casos acima - então as duas opções são aplicáveis, apenas mantenha a consistência (ei, se o acesso ao campo for a opção nessa situação, use-o o tempo todo em situações semelhantes).
01es
fonte
Eu sou novo no Hibernate e estou lutando com a mesma pergunta. Eu acho que este post fornece a resposta mais clara. Obrigado.
Sam Levin
12

Eu recomendo fortemente o acesso ao campo e NÃO as anotações nos getters (acesso à propriedade) se você quiser fazer algo mais nos setters do que apenas definir o valor (por exemplo, criptografia ou cálculo).

O problema com o acesso à propriedade é que os setters também são chamados quando o objeto é carregado. Isso funcionou para mim por muitos meses, até que desejamos introduzir a criptografia. No nosso caso de uso, queríamos criptografar um campo no setter e descriptografá-lo no getter. O problema agora com o acesso à propriedade era que, quando o Hibernate carregava o objeto, ele também estava chamando o setter para preencher o campo e, portanto, estava criptografando o valor criptografado novamente. Esta publicação também menciona o seguinte: Java Hibernate: comportamento da função do conjunto de propriedades diferentes, dependendo de quem está chamando

Isso me causou dores de cabeça até que me lembrei da diferença entre o acesso ao campo e o acesso à propriedade. Agora mudei todas as minhas anotações do acesso à propriedade para o acesso ao campo e agora funciona bem.

Christoph
fonte
Sim - eu descobri que se você usa acesso à propriedade, realmente não pode fazer nada no seu setter além de definir o valor do campo.
HDave
2
+1 Mantenha-se afastado de caçadores / caçadores. Eu uso projectlombok.org e os mantenho escondidos dos desenvolvedores.
bhantol
11

Prefiro usar o acesso ao campo pelos seguintes motivos:

  1. O acesso à propriedade pode levar a erros muito desagradáveis ​​ao implementar equals / hashCode e referenciar campos diretamente (ao contrário de seus getters). Isso ocorre porque o proxy é inicializado apenas quando os getters são acessados, e um acesso direto ao campo retornaria nulo.

  2. O acesso à propriedade requer que você anote todos os métodos utilitários (por exemplo, addChild / removeChild) como @Transient.

  3. Com o acesso ao campo, podemos ocultar o campo @Version não expondo um getter. Um getter também pode levar à adição de um setter, e o versioncampo nunca deve ser definido manualmente (o que pode levar a problemas muito desagradáveis). Todo o incremento de versão deve ser acionado por meio do bloqueio explícito OPTIMISTIC_FORCE_INCREMENT ou PESSIMISTIC_FORCE_INCREMENT .

Vlad Mihalcea
fonte
1. Como a estratégia de acesso ao campo evita isso? Isso parece ser uma armadilha geral com proxies, independentemente do estilo de acesso. 2. Você tem certeza, deve ser apenas getters? (mas um bom argumento de qualquer maneira). 3. Expor os acessadores para o versioncampo geralmente é útil em situações em que os DTOs são usados ​​em vez de entidades desanexadas.
Dragan Bozanovic
1. Por causa de quando um Proxy é inicializado. 2. 100% de certeza. 3. Esse é um ponto válido.
Vlad Mihalcea
Perdoe minha ignorância e possível falta de interpretação do texto (não sou falante nativo de inglês). Apenas para esclarecer, o acesso ao campo é quando não é necessário nenhum método getter / setter, portanto, para um POJO, que é holístico, os campos são públicos? Mas você diz algo no primeiro tópico e o post do blog diz o contrário. O que eu entendi foi que você não pode usar iguais ao utilizar proxies e acesso ao campo.
MaikoID
Não. O acesso ao campo significa que o Hibernate usa os campos através de reflexões para ler os atributos da entidade. Para mais detalhes, consulte a seção Tipo de acesso no Guia do Usuário do Hibernate .
23817 Vlad Mihalcea
7

Acho que anotar a propriedade é melhor porque a atualização de campos quebra diretamente o encapsulamento, mesmo quando o ORM faz isso.

Aqui está um ótimo exemplo de onde ele será gravado: você provavelmente deseja suas anotações para validador de hibernação e persistência no mesmo local (campos ou propriedades). Se você deseja testar as validações ativadas pelo validador de hibernação que estão anotadas em um campo, não é possível usar uma simulação da sua entidade para isolar seu teste de unidade apenas para o validador. Ai.

Justin Standard
fonte
2
É por isso que você colocar Validator- anotações sobre acessores e persistência-anotações em campos
espinha de peixe
6

Eu acredito que o acesso à propriedade vs. o acesso ao campo é sutilmente diferente no que diz respeito à inicialização lenta.

Considere os seguintes mapeamentos para 2 beans básicos:

<hibernate-mapping package="org.nkl.model" default-access="field">
  <class name="FieldBean" table="FIELD_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

<hibernate-mapping package="org.nkl.model" default-access="property">
  <class name="PropBean" table="PROP_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

E os seguintes testes de unidade:

@Test
public void testFieldBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    FieldBean fb = new FieldBean("field");
    Long id = (Long) session.save(fb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    fb = (FieldBean) session.load(FieldBean.class, id);
    System.out.println(fb.getId());
    tx.commit();
    session.close();
}

@Test
public void testPropBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    PropBean pb = new PropBean("prop");
    Long id = (Long) session.save(pb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    pb = (PropBean) session.load(PropBean.class, id);
    System.out.println(pb.getId());
    tx.commit();
    session.close();
}

Você verá a diferença sutil nas seleções necessárias:

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        FIELD_BEAN
        (message, id) 
    values
        (?, ?)
Hibernate: 
    select
        fieldbean0_.id as id1_0_,
        fieldbean0_.message as message1_0_ 
    from
        FIELD_BEAN fieldbean0_ 
    where
        fieldbean0_.id=?
0
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        PROP_BEAN
        (message, id) 
    values
        (?, ?)
1

Ou seja, chamar fb.getId()exige uma seleção, enquanto pb.getId()não exige .

kit de ferramentas
fonte
Isso é engraçado! :) Mas é um comportamento específico da implementação, tenho certeza. I
Vladimir Dyuzhev 27/02/09
Sim, acho que isso se deve ao fato de apenas as classes persistentes serem instrumentadas. No entanto, é uma pena, porque o campo de identificação geralmente é aquele que não tem valor comercial e não precisa de nenhum acessador.
Maurice Perry
6

Deixe-me tentar resumir os motivos mais importantes para escolher o acesso baseado em campo. Se você quiser se aprofundar, leia este artigo no meu blog: Estratégias de acesso no JPA e no Hibernate - Qual é o melhor acesso a campos ou propriedades?

O acesso baseado em campo é de longe a melhor opção. Aqui estão 5 razões para isso:

Razão 1: melhor legibilidade do seu código

Se você usar o acesso baseado em campo, anote seus atributos de entidade com suas anotações de mapeamento. Ao colocar a definição de todos os atributos da entidade no topo da sua classe, você obtém uma visão relativamente compacta de todos os atributos e seus mapeamentos.

Razão 2: Omita métodos getter ou setter que não devem ser chamados pelo seu aplicativo

Outra vantagem do acesso baseado em campo é que seu provedor de persistência, por exemplo, Hibernate ou EclipseLink, não usa os métodos getter e setter dos atributos de sua entidade. Isso significa que você não precisa fornecer nenhum método que não deva ser usado pelo seu código comercial. Geralmente, esse é o caso dos métodos setter de atributos de chave primária gerados ou colunas de versão. Seu provedor de persistência gerencia os valores desses atributos e você não deve defini-los programaticamente.

Razão 3: Implementação flexível dos métodos getter e setter

Como seu provedor de persistência não chama os métodos getter e setter, eles não são forçados a atender a nenhum requisito externo. Você pode implementar esses métodos da maneira que desejar. Isso permite implementar regras de validação específicas de negócios, acionar lógica de negócios adicionais ou converter o atributo de entidade em um tipo de dados diferente.

Você pode, por exemplo, usá-lo para agrupar uma associação ou atributo opcional em um Java Optional.

Razão 4: Não há necessidade de marcar métodos utilitários como @Transient

Outro benefício da estratégia de acesso baseado em campo é que você não precisa anotar seus métodos utilitários com @Transient . Esta anotação informa ao provedor de persistência que um método ou atributo não faz parte do estado persistente da entidade. E como com o acesso por tipo de campo, o estado persistente é definido pelos atributos da sua entidade, sua implementação JPA ignora todos os métodos da sua entidade.

Razão 5: Evite erros ao trabalhar com proxies

O Hibernate usa proxies para associações um-buscadas preguiçosamente, para que ele possa controlar a inicialização dessas associações. Essa abordagem funciona bem em quase todas as situações. Mas apresenta uma armadilha perigosa se você usar o acesso baseado em propriedades.

Se você usar o acesso baseado em propriedades, o Hibernate inicializará os atributos do objeto proxy quando você chamar o método getter. Esse é sempre o caso se você usar o objeto proxy no seu código comercial. Mas muitas implementações iguais e hashCode acessam os atributos diretamente. Se esta é a primeira vez que você acessa algum dos atributos de proxy, esses atributos ainda não foram inicializados.

Thorben Janssen
fonte
3

Por padrão, os provedores JPA acessam os valores dos campos da entidade e mapeiam esses campos para as colunas do banco de dados usando os métodos acessador de propriedade JavaBean (getter) e mutator (setter) da entidade. Como tal, os nomes e tipos dos campos particulares em uma entidade não importam para a JPA. Em vez disso, o JPA examina apenas os nomes e tipos de retorno dos acessadores de propriedade JavaBean. Você pode alterar isso usando a @javax.persistence.Accessanotação, que permite especificar explicitamente a metodologia de acesso que o provedor JPA deve empregar.

@Entity
@Access(AccessType.FIELD)
public class SomeEntity implements Serializable
{
...
}

As opções disponíveis para a enumeração AccessType são PROPERTY (o padrão) e FIELD. Com PROPERTY, o provedor obtém e define valores de campo usando os métodos de propriedade JavaBean. FIELD faz com que o provedor obtenha e defina valores de campo usando os campos da instância. Como prática recomendada, você deve manter o padrão e usar as propriedades JavaBean, a menos que tenha um motivo convincente para fazer o contrário.

Você pode colocar essas anotações de propriedade nos campos particulares ou nos métodos de acesso público. Se você usar AccessType.PROPERTY(padrão) e anotar os campos privados em vez dos acessadores JavaBean, os nomes dos campos deverão corresponder aos nomes das propriedades JavaBean. No entanto, os nomes não precisam corresponder se você anotar os acessadores JavaBean. Da mesma forma, se você usar AccessType.FIELDe anotar os acessadores JavaBean em vez dos campos, os nomes dos campos também deverão corresponder aos nomes das propriedades JavaBean. Nesse caso, eles não precisam corresponder se você anotar os campos. É melhor apenas ser consistente e anotar os acessadores JavaBean AccessType.PROPERTYe os campos para AccessType.FIELD.

É importante que você nunca deve misturar anotações de propriedade JPA e anotações de campo JPA na mesma entidade. Fazer isso resulta em comportamento não especificado e é muito provável que cause erros.

Faraz
fonte
2

Já estamos lá

Essa é uma apresentação antiga, mas Rod sugere que a anotação no acesso à propriedade incentiva modelos de domínio anêmicos e não deve ser a maneira "padrão" de fazer anotações.

Manuel Palacio
fonte
2

Outro ponto a favor do acesso ao campo é que, caso contrário, você será forçado a expor setters para coleções, o que, para mim, é uma má idéia, pois alterar a instância de coleção persistente para um objeto não gerenciado pelo Hibernate definitivamente quebrará a consistência dos dados.

Portanto, prefiro ter coleções como campos protegidos inicializadas para implementações vazias no construtor padrão e expor apenas seus getters. Operações de então, só conseguiu, como clear(), remove(), removeAll()etc são possíveis que nunca vai fazer Hibernate inconsciente de mudanças.

Jiří Vypědřík
fonte
Você não é obrigado a expor nada, pois os setters podem ser protegidos. Além disso, esses setters não fazem parte da interface sendo implementada, portanto, mesmo que fossem públicos, não são facilmente acessíveis.
HDave
2

Eu prefiro campos, mas me deparei com uma situação que parece me forçar a colocar as anotações nos getters.

Com a implementação do Hibernate JPA, @Embeddedparece não funcionar nos campos. Então isso tem que seguir em frente. E uma vez que você coloca isso no getter, as várias @Columnanotações também precisam ir no getter. (Acho que o Hibernate não quer misturar campos e getters aqui.) E uma vez que você coloca @Columngetters em uma classe, provavelmente faz sentido fazer isso o tempo todo.


fonte
2

Eu sou a favor dos acessadores de campo. O código é muito mais limpo. Todas as anotações podem ser colocadas em uma seção de uma classe e o código é muito mais fácil de ler.

Encontrei outro problema com os acessadores de propriedades: se você possui métodos getXYZ em sua classe que NÃO estão anotados como associados a propriedades persistentes, o hibernate gera sql para tentar obter essas propriedades, resultando em algumas mensagens de erro muito confusas. Duas horas perdidas. Eu não escrevi esse código; Eu sempre usei acessadores de campo no passado e nunca encontrei esse problema.

Versões de hibernação usadas neste aplicativo:

<!-- hibernate -->
<hibernate-core.version>3.3.2.GA</hibernate-core.version>
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.1.0.GA</hibernate-commons-annotations.version>
<hibernate-entitymanager.version>3.4.0.GA</hibernate-entitymanager.version>
John Goyer
fonte
2

Você deve escolher o acesso via campos em vez do acesso via propriedades. Com os campos, você pode limitar os dados enviados e recebidos. Com as propriedades via, você pode enviar mais dados como host e definir denominações G (que a fábrica define a maioria das propriedades no total).

user10801787
fonte
1

Eu tive a mesma pergunta sobre o tipo de acesso no hibernate e encontrei algumas respostas aqui .

sundário
fonte
1

Criamos beans de entidade e usamos anotações getter. O problema que encontramos é o seguinte: algumas entidades têm regras complexas para algumas propriedades sobre quando podem ser atualizadas. A solução foi ter alguma lógica de negócios em cada setter que determine se o valor real foi alterado ou não e, se houver, se a alteração deve ser permitida. Obviamente, o Hibernate sempre pode definir as propriedades, então acabamos com dois grupos de configuradores. Bonito feio.

Lendo postagens anteriores, também vejo que a referência às propriedades de dentro da entidade pode levar a problemas com o carregamento de coleções.

Resumindo, gostaria de anotar os campos no futuro.

Steve11235
fonte
0

Normalmente, os beans são POJO, portanto, eles têm acessadores de qualquer maneira.

Portanto, a questão não é "qual é o melhor?", Mas simplesmente "quando usar o acesso ao campo?". E a resposta é "quando você não precisa de um setter / getter para o campo!".

Vladimir Dyuzhev
fonte
4
O problema é que você não pode misturar o acesso de campo e acesso propriedade em um POJO - você tem que escolher um
Martin OConnor
Realmente? Eu devo ter esquecido. De qualquer forma, eu sempre uso POJO e acessadores.
Vladimir Dyuzhev 01/03/09
Observe que, com o JPA 2.0 (que não existia quando essa pergunta foi feita), agora você pode misturar tipos de acesso usando a anotação @AccessType.
mtpettyp
0

Eu estou pensando sobre isso e eu escolho o método accesor

porque?

porque o campo e o methos accesor são os mesmos, mas se mais tarde precisar de alguma lógica no campo de carregamento, salve mover todas as anotações colocadas nos campos

Saudações

Grubhart

user261548
fonte
0

Para tornar suas aulas mais limpas, coloque a anotação no campo e use @Access (AccessType.PROPERTY)

ely
fonte
0

AccessType.PROPERTY: A implementação de persistência EJB carregará o estado em sua classe através dos métodos JavaBean "setter" e recuperará o estado da sua classe usando os métodos JavaBean "getter". Esse é o padrão.

AccessType.FIELD: O estado é carregado e recuperado diretamente dos campos da sua classe. Você não precisa escrever "getters" e "setters" do JavaBean.

Daria Yu
fonte