2009-04-09 13 views
17

Recibo la siguiente excepción cuando intento alterar mi @ID en un @Entity.Hibernar, alterar identificador/clave primaria

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.

He resuelto mediante el uso de esta única consulta HQL: update Table set name=:newName where name=:oldName

lugar de utilizar el enfoque más OO:

beginTransaction(); 
T e = session.load(...); 
e.setName(newName); 
session.saveOrUdate(e); 
commit(); 

Cualquier idea de lo que es la diferencia?

+0

¿Está tratando de usar otra entidad como PK? –

+0

ahora estoy tratando de cambiar mi clave privada de una entidad permanente. en sql sería algo así como: "actualizar Customers set customerId = 1492 donde customer_id = 42;" y customer_id es mi clave privada – Schildmeijer

Respuesta

10

No puedo imaginar por qué querrías hacer eso. En absoluto. ¿Por qué cambiarías la identidad de una entidad? También necesitaría actualizar todas las claves foráneas en otras tablas que lo señalen. Parece un dolor, sin ganancia. Probablemente sea mejor que haga de esto una "clave comercial" (propiedad simple) y use una clave sustituta más permanente. Tengo la sensación de que todo esto va mal, pero si insistes ...

Esencialmente lo que estás haciendo es crear un cliente nuevo y eliminar el anterior, y así es como lo conseguirí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, usted está probablemente mejor sólo lo hace en todos a la vez en una sola transacción de SQL sin formato, y en ambos casos se corre el riesgo de tener procesos paralelos que ya cuentan con una instancia del cliente "antiguo", lo que podría causar algunos errores.

+5

Primero que nada; no hay restricciones de clave externa para esta identidad. Y, por supuesto, hay situaciones en las que uno quiere cambiar la clave principal. Puedo admitir que no es algo que hagas todos los días, pero el contexto puede sin duda crear una situación que lo invoque. – Schildmeijer

+0

Aunque no puedo * imaginar * tal escenario, reconozco que uno podría existir. Me gustaría * amor * saber cuál es este escenario. Además, ¿alguna reflexión sobre la solución propuesta? –

+0

mis intenciones no son groseras. mi escenario es algo como esto Tengo una tabla con dos columnas, nick :: string y number :: int, donde el nick es la clave principal. Y debido a restricciones de memoria incrustadas no podemos permitirnos agregar una identificación como nickId. Y a la gente se le permite cambiar nick – Schildmeijer

3

Mi amigo, tienes razón. No hay forma (o no sé cómo) de cambiar la clave principal sin usar las sentencias HQL. No es normal, pero es verdad.

21

En realidad, de acuerdo con la especificación JPA está prohibido para cambiar una clave principal:

La aplicación no debe cambiar el valor de la clave primaria [8]. El comportamiento no está definido si esto ocurre. [9]

(EJB 3 de persistencia (APP) especificación, párrafo 2.1.4)

+0

No puedo encontrar esto en la versión final. –

3

Esto no es una solución, ya que creo que ha sido respondida anteriormente.

Sin embargo, quería ofrecer lo que consideraba un escenario válido para querer hacer esto. (Comentarios bienvenida)

1) Tabla USER_ELECTRONICS tiene un muchos-a-muchos con la Tabla ELECTRONICS_DEF

2) Este muchos-a-muchos es una lista 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, no tengo tabla USER_ELEC_PRIORITY_MAP, que tiene este aspecto -

USER_ELEC_IDELEC_DEF_IDPRIORITY

1IPAD1
1IPHONE2
1CELL3

USER_ELEC_ID y ELEC_DEF_ID son PFKs. PRIORIDAD es compuesto FK.

3) Cuando quiero volver a cargar la tabla en términos de mis preferencias (Mi nuevo IPad2 está arriba en la lista, y el iPad se mueve a # 4), necesito actualizar parte del FK compuesto (PRIORIDAD).