Respostas:
A transient
palavra-chave Java é usada para indicar que um campo não deve ser serializado, enquanto a @Transient
anotação do JPA é usada para indicar que um campo não deve ser persistido no banco de dados, ou seja, sua semântica é diferente.
Porque eles têm significados diferentes. A @Transient
anotação informa ao provedor JPA para não persistir nenhum transient
atributo (não ). O outro diz à estrutura de serialização para não serializar um atributo. Você pode querer ter uma @Transient
propriedade e ainda serializá-la.
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 gender
e id
não tenta persistir os métodos booleanos auxiliares - sem @Transient
o sistema subjacente reclamará que a classe Entity Person
está ausente setMale()
e com setFemale()
métodos e, portanto, não persistiria Person
.
O objetivo é diferente:
A transient
palavra-chave e a @Transient
anotaçã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 transient
palavra-chave é uma condição mais forte do que @Transient
:
Se um campo usar a transient
palavra - 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 transient
palavra - chave como tendo a @Transient
anotação, o campo também não será mantido pela JPA.
Por outro lado, os campos anotados @Transient
sozinhos serão convertidos em um fluxo de bytes quando o objeto for serializado, mas não serão mantidos pelo JPA. Portanto, a transient
palavra-chave é uma condição mais forte que a @Transient
anotaçã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 ProgressReport
objeto:
@Entity
public class ProgressReport implements Serializable{
private static final long serialVersionUID = 1L;
@Transient
long estimatedMinutesRemaining;
String statusMessage;
Solution currentBestSolution;
}
A Solution
classe pode ficar assim:
@Entity
public class Solution implements Serializable{
private static final long serialVersionUID = 1L;
double[][] dataArray;
Properties properties;
}
O servidor persiste cada um ProgressReport
em 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
.
@Unpersisted
,.
@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") ".
transient
campos como tendo implicitamente a @Transient
anotação. Portanto, se você usar a transient
palavra-chave para impedir a serialização de um campo, ela também não terminará no banco de dados.
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.
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.