Por que o JPA possui uma anotação @Transient?

283

Java tem a transientpalavra - chave Por que o JPA possui, em @Transientvez de simplesmente usar a palavra-chave java já existente?

Deamon
fonte

Respostas:

455

A transientpalavra-chave Java é usada para indicar que um campo não deve ser serializado, enquanto a @Transientanotação do JPA é usada para indicar que um campo não deve ser persistido no banco de dados, ou seja, sua semântica é diferente.

Jawher
fonte
3
Sim, a semântica é diferente. Mas por que o JPA foi projetado dessa maneira?
Dilum Ranatunga
1
Não sei se estou entendendo você, mas dê uma olhada na resposta de "Pascal Thivent";)
Jawher
30
Isso é útil porque você pode não querer armazenar os dados no banco de dados, mas deseja armazená-los no sistema JPA Chaching que usa serialização para armazenar / restaurar entidades.
Kdeveloper 12/12/10
1
Qual "sistema de armazenamento em cache JPA" que usa serialização para armazenamento / restauração de entidades? uma implementação JPA pode armazenar em cache um objeto da maneira que desejar, e a serialização não entra nele.
DataNucleus
@Jawher, aqui, por transitório e não persistente, significa não apresentar nenhum valor ou ele inserirá o valor padrão para esse atributo.
Satish Sharma
115

Porque eles têm significados diferentes. A @Transientanotação informa ao provedor JPA para não persistir nenhum transientatributo (não ). O outro diz à estrutura de serialização para não serializar um atributo. Você pode querer ter uma @Transientpropriedade e ainda serializá-la.

Pascal Thivent
fonte
Obrigado pela resposta Pascal. Como observação do seu comentário: "Você pode querer ter uma propriedade @Transient e ainda serializá-la." (Era isso que eu estava procurando) Também quero acrescentar que o contrário não é verdade. Se alguém definir uma variável como transitória, você não poderá persistir.
jfajunior 23/01
96

Como já foi dito, @Transienté usado para marcar campos que não devem ser mantidos. Considere este pequeno exemplo:

public enum Gender { MALE, FEMALE, UNKNOWN }

@Entity
public Person {
    private Gender g;
    private long id;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }

    public Gender getGender() { return g; }    
    public void setGender(Gender g) { this.g = g; }

    @Transient
    public boolean isMale() {
        return Gender.MALE.equals(g);
    }

    @Transient
    public boolean isFemale() {
        return Gender.FEMALE.equals(g);
    }
}

Quando essa classe é fornecida à JPA, ela persiste gendere idnão tenta persistir os métodos booleanos auxiliares - sem @Transiento sistema subjacente reclamará que a classe Entity Personestá ausente setMale()e com setFemale()métodos e, portanto, não persistiria Person.

Esko
fonte
@psp, você pode explicar mais sobre por que / como isso pode causar um comportamento não especificado? Obrigado!
taiduckman
@ 40Plot os estados da especificação de modo
psp
7
Esta deve ser a resposta aceita no IMHO, pois é muito mais
explícita
53

O objetivo é diferente:

A transientpalavra-chave e a @Transientanotação têm dois propósitos diferentes: um lida com serialização e outro lida com persistência . Como programadores, geralmente casamos esses dois conceitos em um, mas isso não é exato em geral. Persistência refere-se à característica do estado que sobrevive ao processo que o criou. A serialização em Java refere-se ao processo de codificação / decodificação do estado de um objeto como um fluxo de bytes.

A transientpalavra-chave é uma condição mais forte do que @Transient:

Se um campo usar a transientpalavra - chave, esse campo não será serializado quando o objeto for convertido em um fluxo de bytes. Além disso, como a JPA trata os campos marcados com a transientpalavra - chave como tendo a @Transientanotação, o campo também não será mantido pela JPA.

Por outro lado, os campos anotados @Transientsozinhos serão convertidos em um fluxo de bytes quando o objeto for serializado, mas não serão mantidos pelo JPA. Portanto, a transientpalavra-chave é uma condição mais forte que a @Transientanotação.

Exemplo

Isso levanta a questão: por que alguém iria querer serializar um campo que não é persistido no banco de dados do aplicativo? A realidade é que a serialização é usada para mais do que apenas persistência . Em um aplicativo Enterprise Java, é necessário haver um mecanismo para trocar objetos entre componentes distribuídos ; a serialização fornece um protocolo de comunicação comum para lidar com isso. Assim, um campo pode conter informações críticas com a finalidade de comunicação entre componentes; mas esse mesmo campo pode não ter valor da perspectiva da persistência.

Por exemplo, suponha que um algoritmo de otimização seja executado em um servidor e suponha que esse algoritmo leve várias horas para ser concluído. Para um cliente, é importante ter o conjunto de soluções mais atualizado. Portanto, um cliente pode se inscrever no servidor e receber atualizações periódicas durante a fase de execução do algoritmo. Essas atualizações são fornecidas usando o ProgressReportobjeto:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

A Solutionclasse pode ficar assim:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

O servidor persiste cada um ProgressReportem seu banco de dados. O servidor não deseja persistir estimatedMinutesRemaining, mas o cliente certamente se preocupa com essas informações. Portanto, o estimatedMinutesRemainingé anotado usando @Transient. Quando a final Solutioné localizada pelo algoritmo, ela é persistida diretamente pela JPA sem usar a ProgressReport.

Austin D
fonte
1
Se eles realmente são preocupações diferentes, certamente existe uma palavra diferente que captura as nuances. Por que sobrecarregar o termo? Como sugestão inicial @Unpersisted,.
Dilum Ranatunga 12/03/16
4
Eu pessoalmente gosto @Ephemeral. De acordo com Merriam Webster: Quando o efêmero foi impresso pela primeira vez em inglês nos anos 1600, "era um termo científico aplicado a febres de curto prazo e, posteriormente, a organismos (como insetos e flores) com vida útil muito curta. Logo depois disso , adquiriu um sentido estendido referente a qualquer coisa passageira e de vida curta (como em "prazeres efêmeros") ".
Austin D
1
O que também gosto nessa resposta é que ela menciona que a JPA considera os transientcampos como tendo implicitamente a @Transientanotação. Portanto, se você usar a transientpalavra-chave para impedir a serialização de um campo, ela também não terminará no banco de dados.
NeXus
17

Se você deseja apenas que um campo não seja persistido, tanto o transitório quanto o @Transient funcionam. Mas a questão é por que @Transient, já que transitório já existe.

Como o campo @Transient ainda será serializado!

Suponha que você crie uma entidade, fazendo algum cálculo que consome CPU para obter um resultado e esse resultado não será salvo no banco de dados. Mas você deseja enviar a entidade para outros aplicativos Java para usar pelo JMS, então você deve usar @Transient, não a palavra-chave JavaSE transient. Assim, os receptores em execução em outras VMs podem economizar tempo para recalcular novamente.

Sheng.W
fonte
você pode fornecer um exemplo para torná-lo mais claro?
Harsh Kanakhara
existe uma anotação que o jpa tratará como transitório, mas o jackson não?
Kalpesh Soni
0

Vou tentar responder à pergunta do "porquê". Imagine uma situação em que você tenha um enorme banco de dados com muitas colunas em uma tabela e seu projeto / sistema use ferramentas para gerar entidades do banco de dados. (O Hibernate possui esses, etc ...) Agora, suponha que, pela sua lógica de negócios, você precise de um campo específico para NÃO persistir. Você precisa "configurar" sua entidade de uma maneira específica. Embora a palavra-chave Transient funcione em um objeto - como se comporta em uma linguagem java, o @Transient projetado apenas para responder às tarefas que pertencem apenas às tarefas de persistência.

Dima R.
fonte