导读:
orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。
2.ORM的优点和缺点
orm的优点:
隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
ORM使我们构造固化数据结构变得简单易行。
缺点:
无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。
<在python中最著名的ORM是SQLAlchemy>
------------------------------------------------常用代码------------------------
from sqlalchemy import Column, String, create_engine,Integer,func ,ForeignKey,DATE,Table
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy .orm import sessionmaker #创建绘画
from sqlalchemy .orm import relationship #实现反向查找
# 初始化数据库连接:
engine = create_engine('mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8') # echo=True 打印所有信息
# 创建DBSession
DBSession = sessionmaker(bind=engine)
Base=declarative_base() #创建基类
Session_class= sessionmaker(bind=engine) #创建于数据库的会话sessionclass
Session=Session_class() #生成session实例 cursor
(一)数据库的连接
连接mysql
'mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8',echo=True
连接oracle
oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
(数据库类型+基础包+账号+密码+主机+端口+编码方式,字符编码方式,是否显示创建细节)
(一)数据库的连接创建表的结构
from sqlalchemy import create_engine,Table, String,ForeignKey,Integer,DATE
from sqlalchemy.ext.declarative import declarative_base
#①基本表的创建方式一
engine = create_engine('mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8') # echo=True 打印所有信息
DBSession = sessionmaker(bind=engine)
Base=declarative_base() #创建基类
class User(Base):
__tablename__ = 'user' # 表名
id = Column(Integer, primary_key=True)
name = Column(String(32))
password = Column(String(64))
def __repr__(self): #返回打印显示的列
return "<%s name: %s>" % (self.id,self.name)
#②基本表的创建方式二
from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
metadata = MetaData()
#设置表结构
user = Table('user', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(50)),
Column('password', String(12))
)
#将表的结构转化为类的属性
class User(object):
def __init__(self, name, fullname, password):
self.name = name
self.fullname = fullname
self.password = password
mapper(User, user)
③插入数据
Session_class = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
Session = Session_class() #生成session实例
user_obj = User(name="alex",password="alex3714") #生成你要创建的数据对象
#print(user_obj.name,user_obj.id) #此时还没创建对象呢,不信你打印一下id发现还是None
Session.add(user_obj) #把要创建的数据对象添加到这个session里, 一会统一创建
#print(user_obj.name,user_obj.id) #此时也依然还没创建
Session.commit() #现此才统一提交,创建数据
④查询数据-基本查询
data=Session.query(User).filter_by(name='alex').all() #把所有数据取成列表
data=Session.query(User).filter_by(name='alex').first() #取首行数据
#条件查询
data=Session.query(User).filter(User.id==2).all() #条件等于
data=Session.query(User).filter(User.id>2).all() #条件大于
#多条件查询
data=Session.query(User).filter(User.id>2).filter(User.id<4).all() #条件大于
data=Session.query(User).filter(User.id>2).filter(User.id<4).first() #
data.name="zhangsan"
data.password="123"
#统计和分组
data=Session.query(User).filter(User.name.like("al%")).count() #对符合条件的记录进行计数
print(data)
print(Session.query(func.count(User.name),User.name).group_by(User.name).all() ) #对数据进行分组
#数据的修改1
data=Session.query(User).filter(User.id>2).filter(User.id<4).first()
print("change",data) #打印修改后的数据
Session.rollback() #回滚操作
print("rollback",data) #打印修改后的数据
Session.commit()
⑤查询数据-联表查询
ret=Session.query(User,Student).filter(User.name==Student.name).all()
ret=Session.query(User).join(Student).all() #两个表有外键关联的时候才能采用
print(ret)
⑥外键和反向查询
#创建Student表
class Student(Base):
__tablename__ = 'Student' # 表名
id = Column(Integer, primary_key=True)
name = Column(String(32))
register_date=Column(DATE,nullable=False)
def __repr__(self):
return "<%s age: %s>" % (self.name,self.register_date)
#创建StudyRecord表
class StudyRecord(Base):
__tablename__ = 'StudyRecord' # 表名
id = Column(Integer, primary_key=True)
day = Column(Integer,nullable=False)
status = Column(String(64),nullable=False)
stu_id=Column(Integer,ForeignKey('Student.id'))
# student=query(Student).filter(Student.id==stu_obj.stuid).first()
student=relationship("Student",backref="mystudy_record") #这nb允许两张表相互调用反向查找,存在于内存对象中
def __repr__(self):
return "<day:%s status: %s>" % (self.day,self.status)
⑦数据表的一对多(一个客户有不同账单地址和收货地址)
class Customer(Base):
__tablename__ = 'customer'
id = Column(Integer, primary_key=True)
name = Column(String(64))
billing_address_id = Column(Integer, ForeignKey("address.id"))
shipping_address_id = Column(Integer, ForeignKey("address.id"))
billing_address = relationship("Address", foreign_keys=[billing_address_id])#用不同的关联名称
shipping_address = relationship("Address", foreign_keys=[shipping_address_id])#创建的关系只存在于内存对象不会写入数据库
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
street = Column(String(64))
city = Column(String(64))
state = Column(String(64))
def __repr__(self):
return "<street:%s" % (self.street)
⑧多对多
book_m2m_author = Table('book_m2m_author', Base.metadata,
Column('book_id',Integer,ForeignKey('books.id')),
Column('author_id',Integer,ForeignKey('authors.id')),
)
class Author(Base):
__tablename__ = 'author'
id = Column(Integer, primary_key=True)
name = Column(String(40))
def __repr__(self):
return self.name
class Book(Base):
__tablename__ = 'books'
id = Column(Integer,primary_key=True)
name = Column(String(64))
pub_date = Column(DATE)
authors = relationship('authors',secondary=book_m2m_author,backref='books') #多对多,多表关联
def __repr__(self):
return self.name