2011-10-17 17 views
14

En habas POJO Java tal código puede ser beneficioso, especialmente con colecciones:¿Es una buena práctica inicializar campos dentro de un captador de entidades JPA?

class POJO { 
    private Collection<X> col; 

    public Collection<X> getCol() { 
     if (col == null) 
      col = new SomeCollection<X>(); 

     return col; 
    } 
} 

Esto hace posible que el código usando POJO llamar pojo.getCol().isEmpty() sin una comprobación adicional nula, con lo que el código más claro.

Supongamos que la clase POJO es una entidad JPA, ¿todavía es seguro hacerlo? Al inicializar la colección de nula a vacía, los datos persistentes no se modificarán, pero aún así, estamos modificando el objeto y, por lo tanto, el proveedor de persistencia puede ejecutar algunos efectos secundarios al enjuagar el contexto de persistencia. ¿A qué nos arriesgamos? Portabilidad tal vez?

Respuesta

10

No recomendaría la inicialización lenta de las propiedades en una entidad ORM.

Tuvimos un problema grave cuando realizamos la inicialización lenta de una propiedad de entidad usando Hibernate, por lo que lo desalentaría enérgicamente. El problema que vimos se manifestó por una operación de guardado cuando estábamos emitiendo una solicitud de búsqueda. Esto se debe a que cuando se cargó el objeto, la propiedad era nula, pero cuando se llamaba al getter devolvería el objeto inicializado perezoso para que hibernate (correctamente) considerara que el objeto estaba sucio y lo guardaría antes de emitir la búsqueda.

+0

Gracias, eso es lo que he estado buscando, una advertencia de alguien que se quemó haciendo eso. Tenía la corazonada de que podría estar mal, solo que quería asegurarme de no fantasear. – MaDa

+1

seguro. Terminamos pasando 2 días rastreando donde el objeto se estaba ensuciando. Fue bastante doloroso. – digitaljoel

20

No lo veo como una buena práctica, más como una optimización muy rara vez necesaria. Tal vez la inicialización lenta puede tener sentido si SomeCollection es extremadamente difícil de crear. En su lugar puede inicializarlo cuando se declaran (código es más limpio, al menos para mis ojos):

class POJO { 
    private Collection<X> col = new SomeCollection<X>(); 

    public Collection<X> getCol() { 
     return col; 
    } 
} 

no hay efectos secundarios en cuestiones de color o de portabilidad y tiene un cheque nulo menos.

2

En general, es una buena idea utilizar colecciones vacías en su lugar o nulo (para los campos que son colecciones).

Pero no recomiendo la forma en que lo hace en el captador.

En mi opinión personal, la "regla" anterior también se debe usar también para la representación interna del objeto. Así que ve mejor con:

class POJO { 
    private Collection<X> col = new SomeCollection<X>(); 

De todos modos si quieres que desee hacerlo más ahorrar, es necesario proteger todas las formas de actualizar la referencia col. Pero en una aplicación JPA esto debería ser un caso de uso muy crudo.

1

La inicialización lenta es muy común y está bien hacerlo.

Hay ventajas y desventajas en comparación con la inicialización en el constructor o definición de la variable:

Pro

  • inicialización perezosa es en general más eficientes, que difiere los costos de creación de valor, que nunca puede ser requerida o reemplazado con algún otro valor. Esto es muy común en JPA, donde los objetos existentes se leen desde la base de datos, y sus valores siempre se reemplazan.
  • Permite que un valor nulo tenga significado, esto es más típico con valores booleanos, donde null significa el valor predeterminado que se asigna de forma perezosa en función de otra cosa que no se conoce en el momento de la creación.
  • Si el valor es transitorio o anulado de alguna forma, la inicialización diferida puede evitar punteros nulos.

Con

  • Si se accede al campo directamente a usted podría darle un nulo-puntero.
  • Establecer el valor predeterminado en la definición de la variable es más claro.
  • Si el objeto se usa al mismo tiempo, la inicialización diferida puede ser un problema de concurrencia.
Cuestiones relacionadas