sessionmaker()
é uma fábrica, ela existe para encorajar a colocação de opções de configuração para a criação de novos Session
objetos em apenas um lugar. É opcional, pois você poderia facilmente chamar a Session(bind=engine, expire_on_commit=False)
qualquer momento que precisasse de um novo Session
, exceto que é prolixo e redundante, e eu queria impedir a proliferação de "ajudantes" em pequena escala, cada um abordando a questão dessa redundância em algum novo e de forma mais confusa.
Portanto, sessionmaker()
é apenas uma ferramenta para ajudá-lo a criar Session
objetos quando você precisar deles.
Próxima parte. Acho que a questão é: qual é a diferença entre fazer um novo Session()
em vários pontos e apenas usar um até o fim. A resposta, não muito. Session
é um contêiner para todos os objetos que você coloca nele e também mantém o controle de uma transação aberta. No momento em que você chama rollback()
ou commit()
, a transação termina e o Session
não tem conexão com o banco de dados até que seja chamado para emitir SQL novamente. Os links que ele mantém para seus objetos mapeados são referências fracas, desde que os objetos não tenham alterações pendentes, então, mesmo a esse respeito, o Session
irá esvaziar-se de volta para um novo estado quando seu aplicativo perder todas as referências aos objetos mapeados. Se você deixar com o padrão"expire_on_commit"
configuração, todos os objetos expiram após uma confirmação. Se isso Session
durar cinco ou vinte minutos e todos os tipos de coisas mudarem no banco de dados na próxima vez que você usá-lo, ele carregará todos os novos estados da próxima vez que você acessar esses objetos, mesmo que eles estejam na memória por vinte minutos.
Em aplicativos da web, costumamos dizer, ei, por que você não faz um novo Session
em cada solicitação, em vez de usar o mesmo uma e outra vez. Essa prática garante que a nova solicitação comece "limpa". Se alguns objetos da solicitação anterior ainda não foram coletados como lixo e se talvez você tenha desligado "expire_on_commit"
, talvez algum estado da solicitação anterior ainda esteja por aí, e esse estado pode até ser bem antigo. Se você tiver o cuidado de deixar expire_on_commit
ligado e ligar definitivamente commit()
ou rollback()
no final da solicitação, tudo bem, mas se você começar com um novo Session
, então não há dúvida de que você está começando limpo. Portanto, a ideia de iniciar cada solicitação com um novoSession
é realmente apenas a maneira mais simples de ter certeza de que você está começando do zero e de tornar o uso de expire_on_commit
praticamente opcional, já que esse sinalizador pode incorrer em muito SQL extra para uma operação que chama commit()
no meio de uma série de operações. Não tenho certeza se isso responde à sua pergunta.
A próxima rodada é o que você menciona sobre threading. Se seu aplicativo for multithread, recomendamos certificar-se de que o Session
em uso é local para ... algo. scoped_session()
por padrão, torna-o local para o segmento atual. Em um aplicativo da web, o local da solicitação é, na verdade, ainda melhor. Na verdade, o Flask-SQLAlchemy envia uma "função de escopo" personalizada scoped_session()
para que você obtenha uma sessão com escopo de solicitação. O aplicativo Pyramid médio coloca a Sessão no registro de "solicitação". Ao usar esquemas como esses, a ideia "criar uma nova sessão mediante solicitação inicial" continua a parecer a maneira mais direta de manter as coisas em ordem.
Além da excelente resposta do zzzeek, aqui está uma receita simples para criar rapidamente sessões descartáveis e fechadas:
Uso:
fonte