Estoy perdido aquí, y tal vez es algo obvio porque mi experiencia en Hibernate es más débil que en otras áreas.Hibernate cambiar clase incrustable para migrar datos existentes
En el código heredado hay una clase @Entity
de Hibernate Foo
. Uno de los sus propiedades es la siguiente:
private OldBar bar = new OldBar();
OldBar
es una clase @Embeddable
que utiliza una sola columna, foobar
:
@Embeddable
public class OldBar {
private String fooBar;
@Column(length = 10, nullable = false)
private String getFooBar() {
return fooBar;
}
@SuppressWarnings("unused")
private void setFooBar(String fooBar) {
this.fooBar = fooBar;
}
}
El problema original es que tenía que hacer algo con OldBar.fooBar
, pero el el diseño original tenía limitaciones y tenía este campo privado, lo que me impedía crear subclases, así que tuve que crear una clase entera diferente, NewBar
, para reemplazar a la otra y obtener acceso al campo privado. Pensé que desde NewBar
es también Embeddable
y tiene la misma designación @Column
, que sólo podía intercambiar el campo de la clase Foo
:
private NewBar bar = new NewBar();
que quería hacer esto porque tengo los datos existentes en la columna de la foobar
, y Quería usar esta información de manera transparente con NewBar
en lugar de OldBar
.
A través de registros de seguimiento que he visto que Foo()
se crea, con su versión predeterminada de NewBar()
, como uno esperaría, cuando se llama al constructor. Sin embargo, por el código de tiempo llama a Foo.getBar()
, por alguna razón bar
es null
! Supongo que Hibernate lo está configurando en null
por alguna razón, pero ¿por qué Hibernate no lee los datos de la columna foobar
y crea una instancia de NewBar
? ¿Por qué funciona de nuevo cuando pongo OldBar
en lugar de NewBar
? Seguramente no hay nada en la base de datos que indique cuál de las clases @Embeddable
está asignada a la columna, ¿verdad?
Actualización: Esto se vuelve más y más extraño. A veces voy a dejar el código de la noche a la mañana, ¡y al día siguiente funciona! ¡O al día siguiente no funciona! Justo ahora no funcionó (es decir, la propiedad foobar
se estableció en null
en lugar del valor en la base de datos), así que hice la clase ExactCopyOfOldBar
y la puse en el lugar de OldBar
. ¡Funcionó bien! Así que vuelvo a NewBar
--- simplemente deshaciendo mis cambios temporales. ¡Todavía funcionaba, cuando no lo había hecho antes! ¿Hay algún tipo de caché donde Hibernate serialice los valores y no los obtenga de la base de datos? Esto es muy extraño.
Actualización: Ahora ya no puedo obtener NewBar
para funcionar. Creo OtherBar
, que es básicamente idéntico a NewBar
excepto que tiene un nombre diferente, y lo enchufo y funciona, leyendo correctamente la cadena incrustada. Vuelvo a NewBar
, y obtengo null
nuevamente. Que esta pasando?
Nota que Foo
se carga a través de net.databinder.auth.hib.AuthDataApplication.getUser(String username)
, que es bastante simple:
return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass())
.add(Restrictions.eq("username", username)).uniqueResult();
He verificada una y otra vez que el (usuario) tabla Foo
tiene una sola fila con los datos correctos, y lo más importante es que el campo foobar
tiene datos. ¿Por qué Hibernate me devuelve un Foo
con un campo null
foobar
? ¿Por qué simplemente cambiar de NewBar
a OtherBar
hace que comience a funcionar de nuevo? ¿Por qué funciona todo el día y luego deja de funcionar después de haberlo dejado durante la noche?
Supongo que esto es cierto, pero usted no lo dijo: ¿'Foo.bar' está marcado como' @ Embedded'? –
@Tim Pote: De hecho, curiosamente, en el código heredado original (en funcionamiento), _no se marcó como '@ Embedded'. Lo intenté con y sin '@ Embedded' cuando cambié de' OldBar' a 'NewBar', y no hizo la diferencia. –
@Tim Pote: He aprendido de Hibernate [documentación] (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/) que "... si el tipo de propiedad está anotado como @Embeddable, está mapeado como @ Embedded, "por lo que técnicamente la parte' @ Embedded' es opcional. –