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

Java tiene la palabra clave transient . ¿Por qué JPA tiene @Transient lugar de simplemente usar la palabra clave java ya existente?

La palabra clave transient de Java se usa para denotar que un campo no debe ser serializado, mientras que la anotación @Transient de JPA se usa para indicar que un campo no debe persistir en la base de datos, es decir, su semántica es diferente.

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

Como han dicho otros, @Transient se usa para marcar campos que no deberían persistir. Considera este pequeño 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 a la JPA, persiste el gender y la id pero no intenta persistir en los métodos booleanos auxiliares: sin @Transient el sistema subyacente se quejaría de que a la Person clase Entity le faltan los setMale() y setFemale() y por lo tanto no persistiría a la Person en absoluto.

El propósito es diferente:

La palabra clave transient y la anotación @Transient tienen dos propósitos diferentes: uno trata con la serialización y el otro trata con la persistencia . Como progtwigdores, a menudo combinamos estos dos conceptos en uno, pero esto no es exacto en general. La persistencia se refiere a la característica del estado que sobrevive al proceso que la creó. La serialización en Java se refiere al proceso de encoding / deencoding del estado de un objeto como una secuencia de bytes.

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

Si un campo utiliza la palabra clave transient , ese campo no se serializará cuando el objeto se convierta en una secuencia de bytes. Además, dado que JPA considera que los campos marcados con la palabra clave transient tienen la anotación @Transient , JPA tampoco persistirá en el campo.

Por otro lado, los campos anotados como @Transient solo se convertirán en una secuencia de bytes cuando el objeto se serialice, pero JPA no los conservará. Por lo tanto, la palabra clave transient es una condición más sólida que la anotación @Transient .

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 mera persistencia . En una aplicación Enterprise Java, debe haber 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 propósito de comunicación entre componentes; pero ese mismo campo puede no tener valor desde una perspectiva de persistencia.

Por ejemplo, supongamos que se ejecuta un algoritmo de optimización en un servidor, y supongamos que este algoritmo tarda varias horas en completarse. Para un cliente, es importante tener el conjunto de soluciones más actualizado. Entonces, 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 objeto ProgressReport :

 @Entity public class ProgressReport implements Serializable{ private static final long serialVersionUID = 1L; @Transient long estimatedMinutesRemaining; String statusMessage; Solution currentBestSolution; } 

La clase Solution podría verse así:

 @Entity public class Solution implements Serializable{ private static final long serialVersionUID = 1L; double[][] dataArray; Properties properties; } 

El servidor persiste cada informe de ProgressReport en su base de datos. Al servidor no le importa persistir Minutos estimatedMinutesRemaining , pero el cliente ciertamente se preocupa por esta información. Por lo tanto, los @Transient estimatedMinutesRemaining se anotan utilizando @Transient . Cuando la Solution final está ubicada por el algoritmo, JPA la conserva directamente sin utilizar un ProgressReport .

Si solo quiere que un campo no se conserve , tanto el trabajo transitorio como el @Transient funcionan. Pero la pregunta es por qué @Transient ya transitorio ya existe.

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

Supongamos que crea una entidad, haciendo un cálculo de consumo de 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 la use JMS, entonces debe usar @Transient , no la palabra clave JavaSE transient . Por lo tanto, los receptores que se ejecutan en otras VM pueden ahorrar tiempo para volver a calcular.

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