hibernate - tipos - Hibernar, alterar identificador/clave principal
tipos de clave principal en access (4)
En realidad, de acuerdo con la especificación JPA, está prohibido cambiar una clave principal:
La aplicación no debe cambiar el valor de la clave principal [8]. El comportamiento no está definido si esto ocurre. [9]
(de la especificación de persistencia EJB 3 (JPA), párrafo 2.1.4)
Recibo la siguiente excepción cuando intento modificar mi @ID
en una @Entity
.
identifier of an instance of com.google.search.pagerank.ItemEntity was altered from 1 to 2.
Sé que estoy alterando la clave principal en mi tabla. Estoy usando anotaciones JPA.
Resolví esto usando esta única consulta HQL: update Table set name=:newName where name=:oldName
En lugar de utilizar el enfoque más OO:
beginTransaction();
T e = session.load(...);
e.setName(newName);
session.saveOrUdate(e);
commit();
¿Alguna idea de lo que es la diferencia?
Esto no es una solución, ya que creo que se ha respondido anteriormente.
Sin embargo, quería ofrecer lo que consideraba un escenario válido para querer hacer esto. (Comentarios bienvenidos)
1) La tabla USER_ELECTRONICS tiene muchos a muchos con la tabla ELECTRONICS_DEF
2) Esta lista de muchos a muchos es ordenada. Cada USER_ELECTRONIC_ID tiene una lista priorizada de ELECTRONICS_DEF_IDs. Por ejemplo, tengo un iPhone, un IPad, un teléfono celular y los clasifico por orden de cuánto me gustan. Para lograr esto, tengo la tabla USER_ELEC_PRIORITY_MAP, que se ve así:
USER_ELEC_ID
ELEC_DEF_ID
1
IPAD
1
1
IPHONE
2
1
CELL
3
USER_ELEC_ID y ELEC_DEF_ID son PFK. La prioridad es el compuesto FK.
3) Cuando quiero cambiar la tabla en términos de mis preferencias (Mi nuevo IPad2 está en la parte superior de la lista, y el iPad se mueve al # 4), necesito actualizar parte del FK compuesto (PRIORIDAD).
Mi amigo, tienes razón. No hay manera (o no sé) de cambiar la clave principal sin usar sentencias HQL. No es normal, pero es verdad.
No puedo imaginar por qué querrías hacer eso. En absoluto. ¿Por qué cambiarías la identidad de una entidad? También deberías actualizar todas las claves foráneas en otras tablas que lo indiquen. Parece un dolor, sin ganancia. Probablemente sea mejor hacer de esto una "clave de negocio" (propiedad simple) y usar una clave sustituta más permanente. Tengo la sensación de que lo estás haciendo todo mal, pero si insistes ...
Esencialmente, lo que estás haciendo es crear un nuevo Cliente y eliminar el anterior, y así es como lo lograría en Hibernate.
[pseudocódigo]
Begin Transaction
// create new customer from old
newC = Session.Load<Customer>(42)
Session.Evict(newC)
newC.Id = 1492
Session.Save(newC)
// update other relationships to point to newC
// ....
// delete old customer
oldC = Session.Load<Customer>(42)
Session.Delete(oldC)
Commit Transaction
Sin embargo, es probable que sea mejor que lo haga de una sola vez en una simple transacción de SQL, y en ambos casos corre el riesgo de tener procesos paralelos que ya tienen una instancia del "antiguo" Cliente, lo que podría causar algunos errores.