¿Por qué JPA tiene una anotación @Transient?

Respuestas:

455

La transientpalabra clave de Java se usa para denotar que un campo no se debe serializar, mientras que la @Transientanotación de JPA se usa para indicar que un campo no debe persistir en la base de datos, es decir, su semántica es diferente.

Jawher
fuente
3
Sí, la semántica es diferente. Pero, ¿por qué se diseñó JPA de esta manera?
Dilum Ranatunga
1
No estoy seguro de entenderte, pero echa un vistazo a la respuesta de "Pascal Thivent";)
Jawher
30
Esto es útil porque es posible que no desee almacenar los datos en la base de datos, pero sí desea almacenarlos en el sistema JPA Chaching que utiliza la serialización para almacenar / restaurar entidades.
Kdeveloper
1
¿Qué "sistema de almacenamiento en caché JPA" que utiliza la serialización para almacenar / restaurar entidades? una implementación JPA puede almacenar en caché un objeto de la forma que deseen, y la serialización no entra en él.
DataNucleus
@Jawher, aquí para transitorios no presistentes significa no presistir ningún valor o insertará el valor predeterminado para ese atributo.
Satish Sharma
115

Porque tienen diferentes significados. La @Transientanotación le dice al proveedor de JPA que no persista ningún transientatributo (no ). El otro le dice al marco de serialización que no serialice un atributo. Es posible que desee tener una @Transientpropiedad y aún así serializarla.

Pascal Thivent
fuente
Gracias por la respuesta Pascal. Como una nota de su comentario: "Es posible que desee tener una propiedad @Transient y aún así serializarla". (Eso era lo que estaba buscando) También quiero agregar que lo contrario no es cierto. Si uno establece una variable como transitoria, entonces no puede persistirla.
jfajunior
96

Como otros han dicho, @Transientse usa para marcar campos que no deberían persistirse. Considere este breve ejemplo:

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);
    }
}

Cuando esta clase se alimenta al JPA, persiste gendery idno intenta persistir los métodos booleanos auxiliares; sin @Transientel sistema subyacente se quejaría de que Personfaltan la clase Entity setMale()y los setFemale()métodos y, por lo tanto, no persistirían Personen absoluto.

Esko
fuente
@psp ¿puede explicar más sobre por qué / cómo podría causar un comportamiento no especificado? ¡Gracias!
taiduckman
@ 40 Trace los estados de especificación así
psp
77
Esta debería ser, en mi humilde opinión, la respuesta aceptada, ya que explica mucho más que la respuesta aceptada actual ...
Honza Zidek
53

El propósito es diferente:

La transientpalabra clave y la @Transientanotación tienen dos propósitos diferentes: uno trata con la serialización y otro con la persistencia . Como programadores, a menudo combinamos estos dos conceptos en uno solo, pero esto no es exacto en general. La persistencia se refiere a la característica del estado que sobrevive al proceso que lo creó. La serialización en Java se refiere al proceso de codificación / decodificación del estado de un objeto como una secuencia de bytes.

La transientpalabra clave es una condición más fuerte que @Transient:

Si un campo usa la transientpalabra clave, ese campo no se serializará cuando el objeto se convierta en una secuencia de bytes. Además, dado que JPA trata los campos marcados con la transientpalabra clave como teniendo la @Transientanotación, JPA tampoco persistirá en el campo.

Por otro lado, los campos anotados @Transientsolo se convertirán en una secuencia de bytes cuando el objeto se serialice, pero JPA no lo persistirá. Por lo tanto, la transientpalabra clave es una condición más fuerte que la @Transientanotación.

Ejemplo

Esto plantea la pregunta: ¿Por qué alguien querría serializar un campo que no se conserva en la base de datos de la aplicación? La realidad es que la serialización se usa para algo más que la persistencia . En una aplicación Enterprise Java, debe existir un mecanismo para intercambiar objetos entre componentes distribuidos ; la serialización proporciona un protocolo de comunicación común para manejar esto. Por lo tanto, un campo puede contener información crítica con el fin de la comunicación entre componentes; pero ese mismo campo puede no tener valor desde una perspectiva de persistencia.

Por ejemplo, suponga que se ejecuta un algoritmo de optimización en un servidor y suponga que este algoritmo tarda varias horas en completarse. Para un cliente, es importante tener el conjunto de soluciones más actualizado. Por lo tanto, un cliente puede suscribirse al servidor y recibir actualizaciones periódicas durante la fase de ejecución del algoritmo. Estas actualizaciones se proporcionan utilizando el ProgressReportobjeto:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

La Solutionclase podría verse así:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

El servidor persiste cada uno ProgressReporten su base de datos. Al servidor no le importa persistir estimatedMinutesRemaining, pero el cliente ciertamente se preocupa por esta información. Por lo tanto, estimatedMinutesRemainingse anota usando @Transient. Cuando el Solutionalgoritmo localiza el final , JPA lo persiste directamente sin usar a ProgressReport.

Austin D
fuente
1
Si en realidad son preocupaciones diferentes, seguramente existe una palabra diferente que captura los matices. ¿Por qué sobrecargar el término? Como sugerencia de arranque, @Unpersisted.
Dilum Ranatunga
44
Personalmente, me gusta @Ephemeral. Según Merriam Webster: cuando lo efímero se imprimió por primera vez en inglés en el siglo XVII, "era un término científico aplicado a las fiebres a corto plazo y, más tarde, a organismos (como insectos y flores) con una vida muy corta. Poco después de eso , adquirió un sentido extendido que se refiere a cualquier cosa fugaz y de corta duración (como en "placeres efímeros") ".
Austin D
1
Lo que también me gusta de esta respuesta es que menciona que JPA considera que los transientcampos tienen implícitamente la @Transientanotación. Entonces, si usa la transientpalabra clave para evitar la serialización de un campo, tampoco terminará en la base de datos.
neXus
17

Si solo desea que un campo no sea persistente, tanto el transitorio como el @Transient funcionan. Pero la pregunta es por qué @Transient ya que el transitorio ya existe.

¡Porque el campo @Transient todavía se serializará!

Supongamos que crea una entidad, que realiza algunos cálculos que consumen CPU para obtener un resultado y este resultado no se guardará en la base de datos. Pero si desea enviar la entidad a otras aplicaciones Java para que las use JMS, debe usar @Transient, no la palabra clave JavaSE transient. Por lo tanto, los receptores que se ejecutan en otras máquinas virtuales pueden ahorrar su tiempo para volver a calcular.

Sheng.W
fuente
¿Puedes dar un ejemplo para que quede más claro?
Harsh Kanakhara
¿hay alguna anotación que jpa tratará como transitoria pero jackson no?
Kalpesh Soni
0

Trataré de responder la pregunta de "por qué". Imagine una situación en la que tiene una gran base de datos con muchas columnas en una tabla, y su proyecto / sistema utiliza herramientas para generar entidades a partir de la base de datos. (Hibernate tiene esos, etc ...) Ahora, suponga que por su lógica de negocios necesita un campo en particular que NO persista. Tiene que "configurar" su entidad de una manera particular. Si bien la palabra clave Transient funciona en un objeto, ya que se comporta dentro de un lenguaje java, el @Transient solo está diseñado para responder a las tareas que pertenecen solo a tareas de persistencia.

Dima R.
fuente