Per quanto ne so, non c'è modo di convincere l'ORM a emettere inserti in blocco. Credo che il motivo sottostante sia che SQLAlchemy deve tenere traccia dell'identità di ogni oggetto (cioè, nuove chiavi primarie) e gli inserimenti in blocco interferiscono con questo. Ad esempio, supponendo che la foo
tabella contenga una id
colonna ed è mappata a una Foo
classe:
x = Foo(bar=1)
print x.id
# None
session.add(x)
session.flush()
# BEGIN
# INSERT INTO foo (bar) VALUES(1)
# COMMIT
print x.id
# 1
Poiché SQLAlchemy ha rilevato il valore per x.id
senza emettere un'altra query, possiamo dedurre che ha ottenuto il valore direttamente dall'istruzione INSERT
. Se non è necessario un accesso successivo agli oggetti creati tramite le stesse istanze, è possibile saltare il livello ORM per l'inserimento:
Foo.__table__.insert().execute([{'bar': 1}, {'bar': 2}, {'bar': 3}])
# INSERT INTO foo (bar) VALUES ((1,), (2,), (3,))
SQLAlchemy non può abbinare queste nuove righe con alcun oggetto esistente, quindi dovrai interrogarle di nuovo per qualsiasi operazione successiva.
Per quanto riguarda i dati obsoleti, è utile ricordare che la sessione non ha un modo integrato per sapere quando il database viene modificato al di fuori della sessione. Per accedere ai dati modificati esternamente tramite istanze esistenti, le istanze devono essere contrassegnate come scadute . Questo accade per impostazione predefinita session.commit()
, ma può essere fatto manualmente chiamando session.expire_all()
o session.expire(instance)
. Un esempio (SQL omesso):
x = Foo(bar=1)
session.add(x)
session.commit()
print x.bar
# 1
foo.update().execute(bar=42)
print x.bar
# 1
session.expire(x)
print x.bar
# 42
session.commit()
scade x
, quindi la prima istruzione print apre implicitamente una nuova transazione e interroga nuovamente gli x
attributi. Se commentate la prima istruzione print, noterete che la seconda ora prende il valore corretto, perché la nuova query non viene emessa fino a dopo l'aggiornamento.
Ciò ha senso dal punto di vista dell'isolamento transazionale: dovresti rilevare solo le modifiche esterne tra le transazioni. Se questo ti sta causando problemi, suggerirei di chiarire o ripensare i confini delle transazioni della tua applicazione invece di raggiungerli immediatamente session.expire_all()
.