Was ist der richtige Weg, um eine Entität mit JPA schreibgeschützt zu machen? Ich möchte, dass meine Datenbanktabelle niemals programmgesteuert geändert wird.
Ich denke, ich verstehe, dass ich meine Objekte mit sperren sollte LockModeType.READ
. Ist es möglich, eine Anmerkung zu verwenden, um meine Entitäten nach dem Abrufen aus der Datenbank direkt zu sperren? Oder muss ich mein generisches DAO für diese bestimmte Entität herumspielen und überschreiben?
Fügen Sie in Ihrer Entität Folgendes hinzu
EntityListener
:@Entity @EntityListeners(PreventAnyUpdate.class) public class YourEntity { // ... }
Implementieren Sie Ihre
EntityListener
, um eine Ausnahme auszulösen , wenn ein Update auftritt:public class PreventAnyUpdate { @PrePersist void onPrePersist(Object o) { throw new IllegalStateException("JPA is trying to persist an entity of type " + (o == null ? "null" : o.getClass())); } @PreUpdate void onPreUpdate(Object o) { throw new IllegalStateException("JPA is trying to update an entity of type " + (o == null ? "null" : o.getClass())); } @PreRemove void onPreRemove(Object o) { throw new IllegalStateException("JPA is trying to remove an entity of type " + (o == null ? "null" : o.getClass())); } }
Dadurch wird ein kugelsicheres Sicherheitsnetz für Ihr Unternehmen mit JPA-Lifecycle-Listenern erstellt.
quelle
Der Ruhezustand enthält auch eine
org.hibernate.annotations.Immutable
Anmerkung, die Sie dem Typ, der Methode oder dem Feld hinzufügen können.quelle
@Immutable
. Es ist nicht sehr hilfreich. Wenn Sie versuchen, ein Update durchzuführen, tritt kein Fehler auf: Es schlägt nur stillschweigend fehl . Aus der Dokumentation von Hibernate: "Aktualisierungen einer unveränderlichen Entität werden ignoriert, es wird jedoch keine Ausnahme ausgelöst."Wenn sich Ihre JPA-Implementierung im Ruhezustand befindet, können Sie die Annitation "Entity im Ruhezustand" verwenden
@org.hibernate.annotations.Entity(mutable = false)
Dies wird Ihr Modell natürlich an den Ruhezustand binden.
quelle
IIRC Sie könnten jedes Feld auf
insertable = false
undupdatable = false
in Ihren@Column
Anmerkungen setzen, aber ich bin sicher, dass es eine bessere Methode geben muss ... :)Ich nehme nicht an, dass das hilft?
quelle
Ich denke, was Sie suchen, ist Ihre Entität, unveränderlich zu sein. Der Ruhezustand unterstützt dies; JPA (mindestens JPA 1.0) nicht. Ich nehme an, Sie können dies nur steuern, indem Sie nur Getter bereitstellen und sicherstellen, dass die Getter nur unveränderliche Werte zurückgeben.
quelle
Die Eclipselink-Implementierung bietet Ihnen auch die
@ReadOnly
Annotation auf Entitätsebenequelle
Dies wird mich wahrscheinlich abstimmen, weil ich immer abgelehnt werde, weil ich es vorgeschlagen habe, aber Sie können AspectJ auf verschiedene Arten verwenden, um dies durchzusetzen:
Automatisieren Sie entweder die Mac-Lösung (lassen Sie AspectJ die
@Column
Anmerkung einfügen):declare @field : (@Entity *) *.* : @Column(insertable=false);
Oder deklarieren Sie einen Compilerfehler für alle Zugriffe auf festgelegte Methoden:
declare error : execution((@Entity *) *.set*(*) );
Nachteil: Sie müssen Ihrem Build eine AspectJ-Kompilierung hinzufügen, aber das ist einfach, wenn Sie Ant oder Maven verwenden
quelle
declare error
Ansatz ja. Dies funktioniert nur, wenn der aufrufende Code dem AspectJ-Compiler zur Verfügung steht. Der erste Ansatz funktioniert jedoch trotzdem, da er die tatsächlichen Entity-Klassendateien ändert.Wenn Sie Spring-Daten verwenden oder anderweitig das Repository-Muster verwenden, fügen Sie für diese bestimmte Entität keine Methoden zum Speichern / Aktualisieren / Erstellen / Einfügen / usw. in das Repository ein. Dies kann verallgemeinert werden, indem eine Basisklasse / Schnittstelle für schreibgeschützte Entitäten und eine aktualisierbare Klasse vorhanden ist, die die schreibgeschützte für aktualisierbare Entitäten erweitert. Wie andere Poster bereits betont haben, können die Setter auch nicht öffentlich gemacht werden, um zu vermeiden, dass Entwickler versehentlich Werte festlegen, die sie dann nicht speichern können.
quelle