sessionmaker()
è una fabbrica, è lì per incoraggiare l'inserimento di opzioni di configurazione per la creazione di nuovi Session
oggetti in un unico posto. È facoltativo, in quanto potresti facilmente chiamare Session(bind=engine, expire_on_commit=False)
ogni volta che ne avevi bisogno di un nuovo Session
, tranne che è prolisso e ridondante, e volevo fermare la proliferazione di "aiutanti" su piccola scala che ognuno ha affrontato il problema di questa ridondanza in qualche nuovo e modo più confuso.
Quindi sessionmaker()
è solo uno strumento per aiutarti a creare Session
oggetti quando ne hai bisogno.
Parte successiva. Penso che la domanda sia: qual è la differenza tra crearne uno nuovo Session()
in vari punti e usarne uno fino in fondo. La risposta, non molto. Session
è un contenitore per tutti gli oggetti che ci metti e quindi tiene traccia anche di una transazione aperta. Nel momento in cui chiami rollback()
o commit()
, la transazione è terminata e Session
non ha connessione al database finché non viene chiamato a emettere nuovamente SQL. I collegamenti che mantiene agli oggetti mappati sono riferimenti deboli, a condizione che gli oggetti siano privi di modifiche in sospeso, quindi anche a questo riguardo il dispositivo Session
si svuoterà di nuovo in uno stato completamente nuovo quando l'applicazione perde tutti i riferimenti agli oggetti mappati. Se lo lasci con il suo valore predefinito"expire_on_commit"
l'impostazione, quindi tutti gli oggetti scadono dopo un commit. Se Session
rimane in sospeso per cinque o venti minuti e ogni tipo di cose sono cambiate nel database la prossima volta che lo usi, caricherà tutto lo stato nuovo di zecca la prossima volta che accedi a quegli oggetti anche se sono rimasti in memoria per venti minuti.
Nelle applicazioni web, di solito diciamo, ehi, perché non ne crei uno nuovo Session
su ogni richiesta, invece di utilizzare lo stesso più e più volte. Questa pratica garantisce che la nuova richiesta inizi "pulita". Se alcuni oggetti della richiesta precedente non sono stati ancora raccolti in modo indesiderato e se forse li hai disattivati "expire_on_commit"
, forse uno stato della richiesta precedente è ancora in giro e quello stato potrebbe anche essere piuttosto vecchio. Se stai attento a lasciare expire_on_commit
acceso e chiamare definitivamente commit()
o rollback()
alla fine della richiesta, allora va bene, ma se inizi con un nuovo di zecca Session
, allora non c'è nemmeno il dubbio che stai iniziando pulito. Quindi l'idea di iniziare ogni richiesta con una nuovaSession
è davvero solo il modo più semplice per assicurarti di iniziare da zero e per rendere l'uso di expire_on_commit
praticamente opzionale, poiché questo flag può comportare un sacco di SQL extra per un'operazione che chiama commit()
nel mezzo di una serie di operazioni. Non sono sicuro che questo risponda alla tua domanda.
Il prossimo round è quello che hai menzionato sul threading. Se la tua app è multithread, ti consigliamo di assicurarti che quella Session
in uso sia locale per ... qualcosa. scoped_session()
per impostazione predefinita, lo rende locale al thread corrente. In un'app web, localmente alla richiesta è addirittura migliore. Flask-SQLAlchemy invia effettivamente una "funzione di ambito" personalizzata in scoped_session()
modo da ottenere una sessione con ambito di richiesta. L'applicazione Pyramid media inserisce la Session nel registro delle "richieste". Quando si utilizzano schemi come questi, l'idea di "creare una nuova sessione su richiesta di avvio" continua a sembrare il modo più semplice per mantenere le cose chiare.