導(dǎo)讀:
orm英文全稱object relational mapping,就是對(duì)象映射關(guān)系程序,簡單來說我們類似python這種面向?qū)ο蟮某绦騺碚f一切皆對(duì)象,但是我們使用的數(shù)據(jù)庫卻都是關(guān)系型的,為了保證一致的使用習(xí)慣,通過orm將編程語言的對(duì)象模型和數(shù)據(jù)庫的關(guān)系模型建立映射關(guān)系,這樣我們?cè)谑褂镁幊陶Z言對(duì)數(shù)據(jù)庫進(jìn)行操作的時(shí)候可以直接使用編程語言的對(duì)象模型進(jìn)行操作就可以了,而不用直接使用sql語言。
2.ORM的優(yōu)點(diǎn)和缺點(diǎn)
orm的優(yōu)點(diǎn):
隱藏了數(shù)據(jù)訪問細(xì)節(jié),“封閉”的通用數(shù)據(jù)庫交互,ORM的核心。他使得我們的通用數(shù)據(jù)庫交互變得簡單易行,并且完全不用考慮該死的SQL語句??焖匍_發(fā),由此而來。
ORM使我們構(gòu)造固化數(shù)據(jù)結(jié)構(gòu)變得簡單易行。
缺點(diǎn):
無可避免的,自動(dòng)化意味著映射和關(guān)聯(lián)管理,代價(jià)是犧牲性能(早期,這是所有不喜歡ORM人的共同點(diǎn))。現(xiàn)在的各種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 #創(chuàng)建繪畫
from sqlalchemy .orm import relationship #實(shí)現(xiàn)反向查找
# 初始化數(shù)據(jù)庫連接:
engine = create_engine('mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8') # echo=True 打印所有信息
# 創(chuàng)建DBSession
DBSession = sessionmaker(bind=engine)
Base=declarative_base() #創(chuàng)建基類
Session_class= sessionmaker(bind=engine) #創(chuàng)建于數(shù)據(jù)庫的會(huì)話sessionclass
Session=Session_class() #生成session實(shí)例 cursor
(一)數(shù)據(jù)庫的連接
連接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...]
(數(shù)據(jù)庫類型+基礎(chǔ)包+賬號(hào)+密碼+主機(jī)+端口+編碼方式,字符編碼方式,是否顯示創(chuàng)建細(xì)節(jié))
(一)數(shù)據(jù)庫的連接創(chuàng)建表的結(jié)構(gòu)
from sqlalchemy import create_engine,Table, String,ForeignKey,Integer,DATE
from sqlalchemy.ext.declarative import declarative_base
#①基本表的創(chuàng)建方式一
engine = create_engine('mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8') # echo=True 打印所有信息
DBSession = sessionmaker(bind=engine)
Base=declarative_base() #創(chuàng)建基類
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)
#②基本表的創(chuàng)建方式二
from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
metadata = MetaData()
#設(shè)置表結(jié)構(gòu)
user = Table('user', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(50)),
Column('password', String(12))
)
#將表的結(jié)構(gòu)轉(zhuǎn)化為類的屬性
class User(object):
def __init__(self, name, fullname, password):
self.name = name
self.fullname = fullname
self.password = password
mapper(User, user)
③插入數(shù)據(jù)
Session_class = sessionmaker(bind=engine) #創(chuàng)建與數(shù)據(jù)庫的會(huì)話session class ,注意,這里返回給session的是個(gè)class,不是實(shí)例
Session = Session_class() #生成session實(shí)例
user_obj = User(name="alex",password="alex3714") #生成你要?jiǎng)?chuàng)建的數(shù)據(jù)對(duì)象
#print(user_obj.name,user_obj.id) #此時(shí)還沒創(chuàng)建對(duì)象呢,不信你打印一下id發(fā)現(xiàn)還是None
Session.add(user_obj) #把要?jiǎng)?chuàng)建的數(shù)據(jù)對(duì)象添加到這個(gè)session里, 一會(huì)統(tǒng)一創(chuàng)建
#print(user_obj.name,user_obj.id) #此時(shí)也依然還沒創(chuàng)建
Session.commit() #現(xiàn)此才統(tǒng)一提交,創(chuàng)建數(shù)據(jù)
④查詢數(shù)據(jù)-基本查詢
data=Session.query(User).filter_by(name='alex').all() #把所有數(shù)據(jù)取成列表
data=Session.query(User).filter_by(name='alex').first() #取首行數(shù)據(jù)
#條件查詢
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"
#統(tǒng)計(jì)和分組
data=Session.query(User).filter(User.name.like("al%")).count() #對(duì)符合條件的記錄進(jìn)行計(jì)數(shù)
print(data)
print(Session.query(func.count(User.name),User.name).group_by(User.name).all() ) #對(duì)數(shù)據(jù)進(jìn)行分組
#數(shù)據(jù)的修改1
data=Session.query(User).filter(User.id>2).filter(User.id<4).first()
print("change",data) #打印修改后的數(shù)據(jù)
Session.rollback() #回滾操作
print("rollback",data) #打印修改后的數(shù)據(jù)
Session.commit()
⑤查詢數(shù)據(jù)-聯(lián)表查詢
ret=Session.query(User,Student).filter(User.name==Student.name).all()
ret=Session.query(User).join(Student).all() #兩個(gè)表有外鍵關(guān)聯(lián)的時(shí)候才能采用
print(ret)
⑥外鍵和反向查詢
#創(chuàng)建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)
#創(chuàng)建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允許兩張表相互調(diào)用反向查找,存在于內(nèi)存對(duì)象中
def __repr__(self):
return "<day:%s status: %s>" % (self.day,self.status)
⑦數(shù)據(jù)表的一對(duì)多(一個(gè)客戶有不同賬單地址和收貨地址)
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])#用不同的關(guān)聯(lián)名稱
shipping_address = relationship("Address", foreign_keys=[shipping_address_id])#創(chuàng)建的關(guān)系只存在于內(nèi)存對(duì)象不會(huì)寫入數(shù)據(jù)庫
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)
⑧多對(duì)多
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') #多對(duì)多,多表關(guān)聯(lián)
def __repr__(self):
return self.name