O ile wiem, nie ma sposobu, aby ORM wydawał zbiorcze wkładki. Uważam, że głównym powodem jest to, że SQLAlchemy musi śledzić tożsamość każdego obiektu (tj. Nowe klucze podstawowe), a wstawianie zbiorcze koliduje z tym. Na przykład zakładając, że Twoja foo
tabela zawiera id
kolumnę i jest odwzorowana na Foo
klasę:
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
Ponieważ SQLAlchemy pobrał wartość x.id
bez wydawania kolejnego zapytania, możemy wywnioskować, że pobrał wartość bezpośrednio z INSERT
instrukcji. Jeśli nie potrzebujesz późniejszego dostępu do utworzonych obiektów za pośrednictwem tych samych instancji, możesz pominąć warstwę ORM dla swojej wstawki:
Foo.__table__.insert().execute([{'bar': 1}, {'bar': 2}, {'bar': 3}])
# INSERT INTO foo (bar) VALUES ((1,), (2,), (3,))
SQLAlchemy nie może dopasować tych nowych wierszy do żadnych istniejących obiektów, więc będziesz musiał ponownie zapytać o nie w celu wykonania kolejnych operacji.
Jeśli chodzi o nieaktualne dane, warto pamiętać, że sesja nie ma wbudowanego sposobu, aby dowiedzieć się, kiedy baza danych zostanie zmieniona poza sesją. Aby uzyskać dostęp do danych zmodyfikowanych zewnętrznie za pośrednictwem istniejących wystąpień, należy je oznaczyć jako wygasłe . Dzieje się tak domyślnie session.commit()
, ale można to zrobić ręcznie, dzwoniąc session.expire_all()
lub session.expire(instance)
. Przykład (pominięty SQL):
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()
wygasa x
, więc pierwsza instrukcja print niejawnie otwiera nową transakcję i ponownie wysyła zapytanie x
do atrybutów. Jeśli skomentujesz pierwszą instrukcję print, zauważysz, że druga pobiera teraz poprawną wartość, ponieważ nowe zapytanie jest emitowane dopiero po aktualizacji.
Ma to sens z punktu widzenia izolacji transakcyjnej - należy odbierać jedynie zewnętrzne modyfikacje pomiędzy transakcjami. Jeśli sprawia Ci to kłopoty, sugeruję wyjaśnienie lub ponowne przemyślenie granic transakcji w aplikacji zamiast natychmiastowego sięgania po session.expire_all()
.