2012-04-12 25 views
7

Estoy usando la base de datos Oracle y tengo secuencia y desencadenador para generar y almacenar ID antes de insertar.JPA @Id y insertable = false, updatable = false throws excepción

CREATE SEQUENCE CASE_SEQ START WITH 1001 INCREMENT BY 1 NOMAXVALUE; 

CREATE OR REPLACE TRIGGER CASE_TR_SEQ 
BEFORE INSERT ON CASE FOR EACH ROW 
BEGIN 
    SELECT CASE_SEQ.NEXTVAL INTO :NEW.CASE_ID FROM DUAL; 
END; 
/

entonces he simple entidad con la propiedad:

@Id 
@Column(name = "CASE_ID", insertable = false, updatable = false) 
private Long caseId; 

... cuando intento construir proyecto que estoy consiguiendo:

Exception [EclipseLink-46] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): 
org.eclipse.persistence.exceptions.DescriptorException 
Exception Description: There should be one non-read-only mapping defined for the 
primary key field [CASE.CASE_ID]. 

Cuando quito ya sea insertable palabra clave o actualizable , entonces funciona Sé que hay muchas soluciones para generar ID usando JPA, también JPA puede usar (llamar) secuencia de oráculo para establecer ID (generado). Pero trato de entender por qué mis soluciones están equivocadas. ¿Por qué no puedo usar ambas palabras clave junto con la anotación @Id? Mi idea es: Quiero prohibir insertar o actualizar caseId por JPA.

1) ¿Cuál es la verdadera comida? Debo utilizar solamente @Id:

@Id 
@Column(name = "CASE_ID") 
private Long caseId; 

o es mejor (más seguro) definen insertable = false también:

@Id 
@Column(name = "CASE_ID", insertable = false) 
private Long caseId; 

2) Entiendo que actualizable = false para @Id no tiene significado (actualización clave principal no tiene sentido, pero es posible por SQL prima), pero ¿qué significa (¿tiene algún ejemplo cuando es beneficioso):

@Id 
@Column(name = "CASE_ID", updatable = false) 
private Long caseId; 

EDITAR 2012-04-13

Hice algunas pruebas:

Entidad

@Id 
@Column(name = "CASE_ID") 
private Long caseId; 

APP ingrese

INSERT INTO CASE (CASE_ID, CASE_DATE, INFO) VALUES (?, ?, ?) 
bind => [3 parameters bound]|#] 

Así que esto no es seguro, porque la APP intenta tienda CASE_ID (que se sustituye entonces por ID de secuencia de Oracle desencadenar).

Entidad

@Id 
@Column(name = "CASE_ID", insertable = false) 
private Long caseId; 

Crear método

public void createCase(final Case caseData) { 
    caseData.setCaseId(-1001L); 
    em.persist(caseData); 
} 

APP ingrese

INSERT INTO CASE (CASE_DATE, INFO) VALUES (?, ?) 
bind => [2 parameters bound]|#] 

Es bueno, porque el CASE_ID no es parte del comando de inserción.

y actualización de CASE_ID no es posible porque ID anotación:

public void update() { 
    Case update = em.find(Case.class, 1023L); 
    update.setCaseId(1028L); 
} 

Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): 
org.eclipse.persistence.exceptions.ValidationException 
Exception Description: The attribute [caseId] of class 
[com.wordpress.kamiluv.jsfprototype.model.entity.Case] is mapped to a primary 
key column in the database. Updates are not allowed. 

Así que ahora la última versión se ve como el más seguro, ¿verdad?

+1

Eche un vistazo a http://stackoverflow.com/questions/3669883/hibernate-where-do-insertable-false-updatable-false-belong-in-composite-pr y http://stackoverflow.com/questions/3805584/please-explain-about-insertable-false-updatable-false y mira si te ayuda. –

+0

@tech_learner lamentablemente no mucho – Ziletka

+1

No estoy seguro, si ayuda pero ¿estás buscando una clase inmutable? Si es así, échale un vistazo a esto: http://www.mkyong.com/hibernate/hibernate-mutable-example-class-and-collection/ –

Respuesta

5

Actualmente dice con sus anotaciones JPA que tiene una columna @Id que no se puede insertar o actualizar de ninguna manera. Debe poder establecer la identificación antes de insertar o actualizar, pero JPA no sabe cómo hacerlo.Tendrá que usar la anotación @GeneratedValue en @Id para indicarle a JPA qué estrategia usar (una de: TABLE, SEQUENCE, IDENTITY, AUTO) si no desea que se configure el id en su código.

+0

Ok, pero no quiero usar ninguna de las posibilidades de '@GeneratedValue' , Me gustaría utilizar el desencadenador de Oracle para establecer el ID en las columnas de la base de datos. Y eliminar '@Id' no es una buena solución porque hay alguna funcionalidad conectada con '@Id' en JPA, por ejemplo: EntityManager find (Case.class, caseId). – Ziletka

+0

Si solo quiere usar un activador de Oracle, pruebe @GeneratorValue (strategy = GenerationType.AUTO). No estoy seguro acerca de Oracle, pero he tenido éxito con AUTO en una tabla de Sybase que manejaba la generación de id propiamente dicha. – bobz32

+0

funciona, pero creo que no es una buena solución, la estrategia de ATUTO de baca se define por un significado diferente ... DOC: Especificar una estrategia de AUTO permite a EclipseLink seleccionar la estrategia a usar. Normalmente, EclipseLink elige TABLE como estrategia, ya que es la estrategia más portátil. Sin embargo, cuando se especifica AUTO, la generación de esquema se debe usar al menos una vez para que la tabla predeterminada se cree en la base de datos. – Ziletka

Cuestiones relacionadas