Używam bazy danych Oracle i mam sekwencję i wyzwalacz do generowania i przechowywania ID przed wstawieniem.JPA @Id i insertable = false, updatable = false throws wyjątek
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;
/
Wtedy mam proste podmiot z własności:
@Id
@Column(name = "CASE_ID", insertable = false, updatable = false)
private Long caseId;
... gdy próbuję zbudować projekt Dostaję:
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].
Kiedy usunąć albo insercji lub mogą być aktualizowane słowa kluczowego , to działa. Wiem, że istnieje wiele rozwiązań generujących identyfikator za pomocą JPA, także JPA może użyć (wywołać) sekwencji oracle do ustawienia (wygenerowanego) identyfikatora. Ale próbuję zrozumieć, dlaczego moje rozwiązania są złe. Dlaczego nie mogę używać obu słów kluczowych razem z adnotacją @Id? Moją myślą jest: chcę zabronić wstawiania lub aktualizowania caseId przez JPA.
1) Jaka jest właściwa dusza? Należy używać tylko @Id:
@Id
@Column(name = "CASE_ID")
private Long caseId;
lub lepiej (bezpieczniej) określają wkładane = false również:
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
2) Rozumiem, że aktualizowalny = false dla @Id nie mają znaczenia (aktualizacji Klucz podstawowy nie ma znaczenia, ale jest to możliwe przez surowego SQL), ale co to znaczy (czy masz jakiś przykład gdy jest to korzystne):
@Id
@Column(name = "CASE_ID", updatable = false)
private Long caseId;
EDIT 2012-04-13
Zrobiłem kilka testów:
Podmiot
@Id
@Column(name = "CASE_ID")
private Long caseId;
JPA zalogować
INSERT INTO CASE (CASE_ID, CASE_DATE, INFO) VALUES (?, ?, ?)
bind => [3 parameters bound]|#]
Więc to nie jest bezpieczne, ponieważ JPA próbuje sklepu CASE_ID (który jest następnie zastąpiony przez ID z sekwencji Oracle przez cyngiel).
Podmiot
@Id
@Column(name = "CASE_ID", insertable = false)
private Long caseId;
Tworzenie metoda
public void createCase(final Case caseData) {
caseData.setCaseId(-1001L);
em.persist(caseData);
}
JPA zalogować
INSERT INTO CASE (CASE_DATE, INFO) VALUES (?, ?)
bind => [2 parameters bound]|#]
To dobrze, bo CASE_ID nie jest częścią polecenia insert.
i aktualizacja CASE_ID nie jest możliwe, ponieważ adnotacja 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.
Więc teraz ostatnia wersja wygląda jak najbardziej bezpieczne, prawda?
Zobacz http://stackoverflow.com/questions/3669883/hibernate-where-do-insertable-false-updatable-false-belong-in-composite-pr i http://stackoverflow.com/questions/3805584/please-explain-about-insertable-false-updatable-false i zobacz, czy to ci pomaga. –
@tech_learner Niestety nie wiele – Ziletka
Nie jestem pewien, czy to pomaga, ale czy szukasz niezmiennej klasy? Jeśli tak, spójrz na to: http://www.mkyong.com/hibernate/hibernate-mutable-example-class-and-collection/ –