JPA @Id et insérable = false, pouvant être mis à jour = false throws exception
Je suis en utilisant la base de données Oracle et j'ai de la séquence et de déclenchement pour la production et le stockage de carte d'identité avant de l'insérer.
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;
/
Puis j'ai entité avec la propriété:
@Id
@Column(name = "CASE_ID", insertable = false, updatable = false)
private Long caseId;
...quand j'essaie de construction du projet, j'obtiens:
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 le supprime, soit insérable ou mis à jour de mot-clé, puis il travaille. Je sais qu'il y a beaucoup de solutions comment générer des ID en utilisant JPA, aussi JPA pouvez utiliser (appel) oracle séquence de jeu (généré) ID. Mais j'essaie de comprendre pourquoi l'une de mes solutions de mal. Pourquoi je ne peux pas utiliser les deux mots-clés en collaboration avec l'annotation @Id? Ma pensée est: je veux interdire d'insérer ou de mettre à jour caseId par JPA.
1) Quelle est la bonne soulution? Devrais-je utiliser seulement @Id:
@Id
@Column(name = "CASE_ID")
private Long caseId;
ou est meilleur (plus sûr) définir insérable=false également:
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
2) je comprends que pouvant être mis à jour=false pour @Id n'a pas de sens (mise à jour de la Clé Primaire n'a pas de sens, mais il est possible en sql brut), mais que signifient - (avez vous des exemple quand il est bénéfique):
@Id
@Column(name = "CASE_ID", updatable = false)
private Long caseId;
MODIFIER 2012-04-13
J'ai fait quelques tests:
Entité
@Id
@Column(name = "CASE_ID")
private Long caseId;
JPA journal
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 alors remplacé par l'IDENTIFIANT de séquence Oracle par déclenchement).
Entité
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
Méthode de création de la
public void createCase(final Case caseData) {
caseData.setCaseId(-1001L);
em.persist(caseData);
}
JPA journal
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 insert.
Et mise à Jour de CASE_ID n'est pas possible car 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 a l'air comme le plus sûr, non?
malheureusement, pas beaucoup de
Je ne sais pas si ça aide, mais vous êtes à la recherche pour immuable de la classe? Si ensuite, prendre un coup d'oeil à ceci: mkyong.com/hibernate/...
OriginalL'auteur Ziletka | 2012-04-12
Vous devez vous connecter pour publier un commentaire.
Vous êtes actuellement en disant avec votre JPA annotations que vous avez un @colonne Id qui ne peuvent pas être insérées ou mises à jour en quelque sorte. Vous devez être en mesure de définir l'id avant d'insérer ou de mettre à jour, mais JPA ne sais pas comment faire. Vous aurez besoin d'utiliser le @GeneratedValue annotation @Id dire JPA ce que la stratégie à utiliser (l'un des: TABLEAU,l'ordre,l'IDENTITÉ,l'AUTO) si vous ne voulez pas l'id pour être mis dans votre code.
Si vous voulez juste utiliser un Oracle de déclenchement, essayez @GeneratorValue(stratégie=GenerationType.AUTO). Pas sûr au sujet de l'Oracle, mais j'ai eu du succès avec l'AUTO sur une Sybase tableau qui s'occupait de la génération de code lui-même.
il fonctionne, mais je pense qu'il n'est pas de bonnes solutions, bacuase ATUTO stratégie est définie pour les différents sens... DOC: la Spécification d'une stratégie d'AUTO permet EclipseLink pour sélectionner la stratégie à utiliser. Généralement, EclipseLink choisit de TABLE comme la stratégie, puisqu'il est le plus portable de la stratégie. Cependant, quand l'AUTO est spécifié, la génération de schéma doit être utilisé au moins une fois dans l'ordre de la table par défaut sera créé dans la base de données.
La seule autre solution que je pouvais penser de nécessiterait une modification à votre détente. Si vous avez fait votre de déclenchement conditionnel (si l'id n'est pas spécifié, ALORS l'utilisation et l'incrément de la SÉQUENCE), vous pouvez utiliser le générateur de SÉQUENCE type en JPA. De cette façon, votre code à l'aide de la SÉQUENCE correctement, et votre détente gérer tout l'héritage SQL insert en même temps.
Oui, la bonne solution, mais il y a peut être un problème que certains développeur ensemble caseId et ensuite appeler la méthode em.persist(). Le nouveau cas sera stocké dans la base de données avec le "non" sequnce ID. Je vais essayer de faire quelques tests de la solution qui est la plus sûre.
OriginalL'auteur bobz32