SQLAlchemy constitui a biblioteca ORM mais amplamente adotada no ecossistema Python, oferecendo mecanismos sofisticados para interação com bases de dados relacionais. Este artigo apresenta uma abordagem estruturada para utilização do SQLAlchemy ORM, abordando desde a configuração inicial até operações avançadas de persistência.
Sumário
- Configuração do Ambiente
- Fundamentos e Componentes Principais
- Estabelecimento de Conexões
- Mapeamento de Entidades
- Criação de Estruturas de Dados
- Operações de Persistência
- Consultas e Filtros
- Relacionamentos Entre Entidades
- Controle de Transações
- Recomendações e Padrões
Configuração do Ambiente
bash
pip install sqlalchemy
Dependendo do banco de dados utilizado, faz-se necessária a instalação de drivers específicos:
bash
# PostgreSQL
pip install psycopg2-binary
# MySQL
pip install pymysql
# SQLite (já incluso na biblioteca padrão do Python)
Fundamentos e Componentes Principais
- Engine: Motor responsável pela comunicação com o servidor de banco de dados
- Session: Sessão que gerencia todas as operações de persistência
- Model: Classes que representam entidades do banco de dados
- Query: Construção de consultas ao banco de dados
Estabelecimento de Conexões
python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# Configuração do mecanismo de conexão
# Exemplo com SQLite
engine = create_engine('sqlite:///application.db', echo=True)
# Exemplo com PostgreSQL
# engine = create_engine('postgresql://usuario:senha@localhost:5432/meubanco')
# Exemplo com MySQL
# engine = create_engine('mysql+pymysql://usuario:senha@localhost:3306/meubanco')
# Fábrica de sessões
SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# Instância de sessão
sessao = SessionFactory()
Mapeamento de Entidades
python
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, declarative_base
# Classe base para modelos
ModeloBase = declarative_base()
class Autor(ModeloBase):
__tablename__ = 'autores'
identificador = Column(Integer, primary_key=True, index=True)
nome = Column(String(50), nullable=False)
email = Column(String(100), unique=True, index=True)
# Relacionamento um-para-muitos
artigos = relationship("Artigo", back_populates="criador")
class Artigo(ModeloBase):
__tablename__ = 'artigos'
identificador = Column(Integer, primary_key=True, index=True)
titulo = Column(String(100), nullable=False)
corpo = Column(String(500))
autor_id = Column(Integer, ForeignKey('autores.id'))
# Relacionamento muitos-para-um
criador = relationship("Autor", back_populates="artigos")
# Relacionamento muitos-para-muitos (via tabela associativa)
categorias = relationship("Categoria", secondary="artigo_categorias", back_populates="artigos")
class Categoria(ModeloBase):
__tablename__ = 'categorias'
identificador = Column(Integer, primary_key=True, index=True)
rotulo = Column(String(30), unique=True, nullable=False)
artigos = relationship("Artigo", secondary="artigo_categorias", back_populates="categorias")
# Tabela associativa para relacionamento muitos-para-muitos
class ArtigoCategoria(ModeloBase):
__tablename__ = 'artigo_categorias'
artigo_id = Column(Integer, ForeignKey('artigos.id'), primary_key=True)
categoria_id = Column(Integer, ForeignKey('categorias.id'), primary_key=True)
Criação de Estruturas de Dados
python
# Geração de todas as tabelas definidas
ModeloBase.metadata.create_all(bind=engine)
# Remoção de todas as tabelas
# ModeloBase.metadata.drop_all(bind=engine)
Operações de Persistência
Inserção de Registros
python
# Criação de novo autor
novo_autor = Autor(nome="João Silva", email="joao@exemplo.com")
sessao.add(novo_autor)
sessao.commit()
# Inserção em lote
sessao.add_all([
Autor(nome="Maria Santos", email="maria@exemplo.com"),
Autor(nome="Pedro Oliveira", email="pedro@exemplo.com")
])
sessao.commit()
Recuperação de Dados
python
# Obter todos os autores
autores = sessao.query(Autor).all()
# Obter primeiro registro
primeiro_autor = sessao.query(Autor).first()
# Buscar por identificador
autor = sessao.query(Autor).get(1)
Atualização de Registros
python
# Consulta e modificação
autor = sessao.query(Autor).get(1)
autor.nome = "João Santos"
sessao.commit()
# Atualização em massa
sessao.query(Autor).filter(Autor.nome.like("Jo%")).update({"nome": "Jose"}, synchronize_session=False)
sessao.commit()
Remoção de Registros
python
# Consulta e exclusão
autor = sessao.query(Autor).get(1)
sessao.delete(autor)
sessao.commit()
# Exclusão em massa
sessao.query(Autor).filter(Autor.nome == "Maria Santos").delete(synchronize_session=False)
sessao.commit()
Consultas e Filtros
Consultas Básicas
python
# Recuperação completa
autores = sessao.query(Autor).all()
# Seleção de campos específicos
nomes = sessao.query(Autor.nome).all()
# Ordenação decrescente
autores = sessao.query(Autor).order_by(Autor.nome.desc()).all()
# Limitação de resultados
autores = sessao.query(Autor).limit(10).all()
# Aplicação de offset
autores = sessao.query(Autor).offset(5).limit(10).all()
Filtros Condicionais
python
from sqlalchemy import or_
# Filtragem por igualdade
autor = sessao.query(Autor).filter(Autor.nome == "João Silva").first()
# Busca por padrão
autores = sessao.query(Autor).filter(Autor.nome.like("Jo%")).all()
# Verificação em lista
autores = sessao.query(Autor).filter(Autor.nome.in_(["João Silva", "Maria Santos"])).all()
# Múltiplas condições
autores = sessao.query(Autor).filter(
Autor.nome == "João Silva",
Autor.email.like("%@exemplo.com")
).all()
# Condição OR
autores = sessao.query(Autor).filter(
or_(Autor.nome == "João Silva", Autor.nome == "Maria Santos")
).all()
# Diferença
autores = sessao.query(Autor).filter(Autor.nome != "João Silva").all()
Funções de Agregação
python
from sqlalchemy import func
# Contagem total
total = sessao.query(Autor).count()
# Agrupamento com contagem
contagem_artigos = sessao.query(
Autor.nome,
func.count(Artigo.identificador)
).join(Artigo).group_by(Autor.nome).all()
# Cálculos estatísticos
media_id = sessao.query(func.avg(Autor.identificador)).scalar()
Junções de Tabelas
python
# Inner join
resultados = sessao.query(Autor, Artigo).join(Artigo).filter(Artigo.titulo.like("%Python%")).all()
# Left outer join
resultados = sessao.query(Autor, Artigo).outerjoin(Artigo).all()
# Junção com condição explícita
resultados = sessao.query(Autor, Artigo).join(Artigo, Autor.identificador == Artigo.autor_id).all()
Relacionamentos Entre Entidades
python
# Criação de entidades relacionadas
autor = Autor(nome="Carlos Pereira", email="carlos@exemplo.com")
artigo = Artigo(titulo="Introdução ao SQLAlchemy", corpo="Conteúdo inicial...", criador=autor)
sessao.add(artigo)
sessao.commit()
# Acesso através de relacionamentos
print(f"Artigo '{artigo.titulo}' criado por {artigo.criador.nome}")
print(f"Artigos do autor {autor.nome}:")
for a in autor.artigos:
print(f" - {a.titulo}")
# Operações em relacionamentos muitos-para-muitos
categoria_python = Categoria(rotulo="Python")
categoria_bd = Categoria(rotulo="Banco de Dados")
artigo.categorias.append(categoria_python)
artigo.categorias.append(categoria_bd)
sessao.commit()
print(f"Categorias do artigo '{artigo.titulo}':")
for cat in artigo.categorias:
print(f" - {cat.rotulo}")
Controle de Transações
python
# Gerenciamento automático de transações
try:
autor = Autor(nome="Usuario Teste", email="teste@exemplo.com")
sessao.add(autor)
sessao.commit()
except Exception as erro:
sessao.rollback()
print(f"Erro detectado: {erro}")
# Utilização de gerenciador de contexto
from sqlalchemy.orm import Session
def criar_autor(sessao: Session, nome: str, email: str):
try:
autor = Autor(nome=nome, email=email)
sessao.add(autor)
sessao.commit()
return autor
except:
sessao.rollback()
raise
# Transações aninhadas
with sessao.begin_nested():
autor = Autor(nome="Usuario Transacao", email="transacao@exemplo.com")
sessao.add(autor)
# Savepoints
ponto_salvamento = sessao.begin_nested()
try:
autor = Autor(nome="Usuario Savepoint", email="savepoint@exemplo.com")
sessao.add(autor)
ponto_salvamento.commit()
except:
ponto_salvamento.rollback()
Recomendações e Padrões
- Gerenciamento de Sessões: Criar uma nova sessão para cada requisição e encerrá-la adequadamente
- Traatmento de Exceções: Implementar tratamento robusto e realizar rollback quando necessário
- Carregamento Antecipado: Evitar problemas de N+1 queries utilizando eager loading
- Pool de Conexões: Configurar adequadamente o tamanho do pool e tempos limite
- Validação de Dados: Implementar validações no nível do modelo ou da aplicação
python
# Gerenciamento de sessões com contextlib
from contextlib import contextmanager
@contextmanager
def obter_sessao():
db = SessionFactory()
try:
yield db
db.commit()
except Exception:
db.rollback()
raise
finally:
db.close()
# Exemplo de utilização
with obter_sessao() as db:
autor = Autor(nome="Usuario Contexto", email="contexto@exemplo.com")
db.add(autor)
Considerações Finais
SQLAlchemy ORM constitui uma ferramenta extremamente versátil para operações de persistência em Python. Após a apresentação dos conceitos fundamentais deste artigo, você estará capacitado a:
- Configurar e inicializar o SQLAlchemy adequadamente
- Criar modelos de dados e definir relacionamentos
- Executar operações completas de persistência
- Desenvolver consultas sophisticatedas
- Implementar controle transacional robusto
- Aplicar boas práticas de desenvolvimento
O SQLAlchemy oferece inúmeras funcionalidades adicionais, incluindo propriedades híbridas, sistemas de eventos e extensões personalizadas de consulta, que merecem aprofundamento em estudos posteriores.