web-dev-qa-db-de.com

Wie verhindere ich, dass Spring Data JPA vor einem save () ein SELECT ausführt?

Wir schreiben eine neue App für eine vorhandene Datenbank. Ich verwende Spring Data JPA und mache einfach eine 

MyRepository.save() 

auf meiner neuen Entität verwenden 

MyRepository extends CrudRepository<MyThing, String>

In den Protokollen ist mir aufgefallen, dass der Ruhezustand vor dem Einfügen ein Select ausführt und dass diese Zeit sehr lange dauert, selbst wenn die Indizes verwendet werden. 

Ich habe das hier gesucht und die Antworten, die ich gefunden habe beziehen sich normalerweise auf Hibernate. Ich bin ziemlich neu bei JPA und es scheint, als seien JPA und Hibernate ziemlich eng miteinander verbunden, zumindest wenn sie im Rahmen von Spring Data verwendet werden. Die verknüpften Antworten schlagen die Verwendung von Hibernate persist () oder irgendwie eine Sitzung vor, möglicherweise von einem entityManager? Ich hatte nichts mit Sessions oder entityManagers oder direkt mit einer Hibernate-API zu tun. Bisher habe ich einfache Einfügungen mit save () und ein paar @Query in meinen Repositories gemacht.

7
user26270

Hier ist der Code von Spring SimpleJpaRepository, das Sie mit Spring Data Repository verwenden:

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

Es tut Folgendes:

Standardmäßig prüft Spring Data JPA die Bezeichner-Eigenschaft der angegebenen Entität. Wenn die Bezeichner-Eigenschaft null ist, wird die Entität als neu angenommen, andernfalls als nicht neu.

Link zur Spring Data-Dokumentation

Wenn also eines Ihrer Entitäten ein ID-Feld hat, das nicht null ist, veranlasst Spring, dass Hibernate ein Update ausführt (und zuvor ein SELECT).

Sie können dieses Verhalten auf zwei Arten überschreiben, die in derselben Dokumentation aufgeführt sind. Eine einfache Möglichkeit besteht darin, dass Ihre Entity Persistable (anstelle von Serializable) implementiert, wodurch Sie die Methode "isNew" implementieren.

11
Bertrand88

Wenn Sie Ihren eigenen ID-Wert angeben, geht Spring Data davon aus, dass Sie den DB auf einen doppelten Schlüssel überprüfen müssen (daher select + insert).

Besser ist es, einen ID-Generator zu verwenden:

@Entity
public class MyThing {
    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    private UUID id;
}

Wenn Sie wirklich Ihre eigene ID eingeben müssen und das Auswählen + Einfügen verhindern möchten, implementieren Sie Persistable, z.

@Entity
public class MyThing implements Persistable<UUID> {

    @Id
    private UUID id;

    @Override
    public UUID getId() {
        return id;
    }

    //prevent Spring Data doing a select-before-insert - this particular entity is never updated
    @Override
    public boolean isNew() {
        return true;
    }
}
2
Paul Hilliar