Ich arbeite an einer Spring Boot-Anwendung, die JPA (Hibernate) für die Persistenzschicht verwendet.Bulk Einfügen vorhandener Daten: Verhindern, dass JPA vor jedem Einfügen eine Auswahl trifft
Ich implementiere derzeit eine Migrationsfunktionalität. Wir deponieren grundsätzlich alle vorhandenen Entitäten des Systems in eine XML-Datei. Dieser Export enthält auch IDs der Entitäten.
Das Problem, das ich habe, befindet sich auf der anderen Seite, Reimportieren der vorhandenen Daten. In diesem Schritt wird das XML erneut in ein Java-Objekt umgewandelt und in der Datenbank gespeichert.
Beim Versuch, die Entität zu speichern, verwende ich die merge
Methode der EntityManager
Klasse, die funktioniert: alles wird erfolgreich gespeichert.
Wenn ich jedoch die Abfrageprotokollierung von Hibernate aktiviere, sehe ich, dass vor jeder Einfügeabfrage eine Auswahlabfrage ausgeführt wird, um festzustellen, ob eine Entität mit dieser ID bereits existiert. Dies liegt daran, dass die Entität bereits eine von mir angegebene ID hat.
Ich verstehe dieses Verhalten und es macht tatsächlich Sinn. Ich bin mir aber sicher, dass die IDs nicht existieren werden, so dass die Auswahl für meinen Fall keinen Sinn ergibt. Ich speichere Tausende von Datensätzen, so dass Tausende von Select-Abfragen für große Tabellen erforderlich sind, was den Importprozess drastisch verlangsamt.
Meine Frage: Gibt es eine Möglichkeit, dies zu ändern "zu überprüfen, ob eine Entität existiert vor dem Einfügen" aus?
Zusätzliche Informationen:
Wenn ich entityManager.persist()
statt Druck verwenden, erhalte ich diese Ausnahme:
org.hibernate.PersistentObjectException: freistehende Einheit geben bestehen
Um eine mitgelieferte/bereitgestellte ID verwenden zu können, verwende ich diesen ID-Generator:
@Id
@GeneratedValue(generator = "use-id-or-generate")
@GenericGenerator(name = "use-id-or-generate", strategy = "be.stackoverflowexample.core.domain.UseIdOrGenerate")
@JsonIgnore
private String id;
Der Generator selbst:
public class UseIdOrGenerate extends UUIDGenerator {
private String entityName;
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
entityName = params.getProperty(ENTITY_NAME);
super.configure(type, params, serviceRegistry);
}
@Override
public Serializable generate(SessionImplementor session, Object object)
{
Serializable id = session
.getEntityPersister(entityName, object)
.getIdentifier(object, session);
if (id == null) {
return super.generate(session, object);
} else {
return id;
}
}
}
Danke, das habe ich vergessen zu erwähnen. Ich habe versucht, persist zu verwenden, aber es löst eine Ausnahme aus. Ich habe meinen ursprünglichen Beitrag mit den Details aktualisiert. – geoffreydv
Wenn Sie in der Lage sind, Änderungen vorzunehmen, überprüfen Sie meine upadte –
Das ist eine gute Idee, aber wenn ich richtig verstehe, würde dies Einfügen neuer Elemente in allen anderen Teilen der Anwendung brechen, weil die IDs leer sein wird. Ich müsste überall manuell eine setId (generateId()) machen, was momentan keine Option ist. – geoffreydv