JPA 2 – Entity extends abastract non-entity

Essa dica é boa. Hoje eu enfrentei o seguinte problemas:

Criei uma entity que extende uma classe abstrata que não é um entity.

A classe abaixo não pode ser uma entity, mas será super classe de uma entity. Ou seja essa classe não pode ter nenhuma anotação JPA.

public abstract class AbstractMessage {  
  
    protected String textMessage;  

    public String getTextMessage() {  
        return textMessage;  
    }  
      
    public void setTextMessage(String textMessage) {  
        this.textMessage = textMessage;  
    }    
}  

A entity abaixo extende a classe AbstractMessage e sobrescreve os métodos getTextMessage e setTextMessage.

@Entity  
@Table(name = "MessageLog")  
@NamedQueries({  
        @NamedQuery(name = "MessageLog.findById", query = "select a from MessageLog a where a.id = :id"),  
        @NamedQuery(name = "MessageLog.findAll", query = "select a from MessageLog a")})  
  
    public class MessageLog extends AbstractMessage implements IEntity {  
    private static final long serialVersionUID = 8575100237171444046L;  
      
    @Id   
    @GeneratedValue(strategy = GenerationType.IDENTITY)  
    @Column(name = "MessageLogId")  
    private Integer id;   
  
    public Integer getId() {  
        return this.id;  
    }  
  
    public void setId(Integer id) {  
        this.id = id;  
    }  
  
    @Override  
    @Column(name = "TextMessage", nullable = false)  
    public String getTextMessage() {  
        return super.textMessage;  
    }  
  
    @Override  
    public void setTextMessage(String textMessage) {  
        super.textMessage = textMessage;  
    }  
  
   //Existem outros atributos mas não vem ao caso.  
Meu problema era que ao enviar a entity MessageLog para o entityManager persistir eu recebia uma exception informando que o campo TextMessage estava nulo, mesmo eu verificando através do debug que não estava.

Veja bem na super classe (AbstractMessage), o atributo textMessage estava com a visibilidade protected, ou seja ele é visivel pela classe filha. Como a classe abstrata neste caso não poderia receber nenhuma anotação JPA a anotação com os dados da coluna foram inseridas na propriedade getTextMessage(). Ao debugar a aplicação era visível a informação de textMessage sendo setada através do setTextMessage(String textMessage).

Porque então o valor era entendido como null ao ser processado no entityManager ?

Resposta: JPA suporta dois tipos de acesso à fields. Via fields e via properties. Via Field, os binds serão feitos diretamente nas variáveis da instância, e via property, via seus Setters and Getters. O que determina qual deles usar, é onde você configura sua @Id.
Quando eu tirei as anotações dos atributo e coloquei nos gets o problema desapareceu.

Uma outra forma de controlar esse comportamento é através da annotation @Access, porém eu não testei ela.

Referências
Persistent Fields and Properties in Entity Classes
Entity Inheritance
JPA 2, The Access annotation
JPA Implementation Patterns: Field Access vs. Property Access

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s