J'utilise la base de données Oracle et j'ai une séquence et un déclencheur pour générer et stocker l'ID avant l'insertion.JPA @Id et insertable = false, updatable = false jette l'exception
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;
/
Ensuite, je dois entité simple avec la propriété:
@Id
@Column(name = "CASE_ID", insertable = false, updatable = false)
private Long caseId;
... lorsque je tente construire des projets que je reçois:
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].
Lorsque je supprimer soit mot-clé insérable ou actualisable , alors ça marche. Je sais qu'il y a beaucoup de solutions pour générer des ID en utilisant JPA, et JPA peut aussi utiliser (call) une séquence oracle pour définir des ID (générés). Mais j'essaie de comprendre pourquoi mes solutions sont fausses. Pourquoi je ne peux pas utiliser les deux mots clés avec l'annotation @Id? Ma pensée est la suivante: Je veux interdire l'insertion ou la mise à jour de caseId par JPA.
1) Quelle est la bonne soulution? Dois-je utiliser seulement @Id:
@Id
@Column(name = "CASE_ID")
private Long caseId;
ou est meilleure (plus sûr) insérable = false définir aussi:
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
2) Je comprends que actualisable = false pour @Id n'a pas de sens (mise à jour clé primaire n'a pas de signification, mais il est possible par sql cru), mais qu'est-ce que cela veut dire (avez-vous quelques exemples quand il est bénéfique):
@Id
@Column(name = "CASE_ID", updatable = false)
private Long caseId;
EDIT 2012-04-13
J'ai fait quelques tests:
Entité
@Id
@Column(name = "CASE_ID")
private Long caseId;
JPA log
INSERT INTO CASE (CASE_ID, CASE_DATE, INFO) VALUES (?, ?, ?)
bind => [3 parameters bound]|#]
Donc, ce n'est pas sûr, parce que JPA essaie magasin CASE_ID (qui est ensuite remplacé par ID de la séquence Oracle par déclencheur).
Entité
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
Créer méthode
public void createCase(final Case caseData) {
caseData.setCaseId(-1001L);
em.persist(caseData);
}
JPA log
INSERT INTO CASE (CASE_DATE, INFO) VALUES (?, ?)
bind => [2 parameters bound]|#]
Il est bon, parce que le CASE_ID ne fait pas partie de la commande d'insertion.
et mise à jour de CASE_ID n'est pas possible parce que l'annotation ID:
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.
Alors maintenant, la dernière version se présente comme le plus sûr, non?
Jetez un oeil à http://stackoverflow.com/questions/3669883/hibernate-where-do-insertable-false-updatable-false-belong-in-composite-pr et http://stackoverflow.com/questions/3805584/please-explain-about-insertable-false-updatable-false et voyez si cela vous aide. –
@tech_learner malheureusement pas beaucoup – Ziletka
Je ne suis pas sûr, si cela aide, mais vous cherchez une classe immuable? Si oui, jetez un oeil à ceci: http://www.mkyong.com/hibernate/hibernate-mutable-example-class-and-collection/ –