zoukankan      html  css  js  c++  java
  • 利用SQLAlchemy和反射实现DAO的基类

    在使用SQLAlchemy时,要根据每一个类的情况写对应增删改查,习惯了JAVA的虚类、反射,抽象出daobase类,如果python也有就会少很多重复代码,于是有了下面的简单实现。

    注:我的Entity都是最简单的没有其他方法,只有属性,如以下例子:

    Base = declarative_base()
    class StudentBasicInfo(Base):
        """
        学生基本信息类
        表名: studentbasic
        用于记录学生最基本的信息,在导入时清除以前数据,用新的数据替换。
        """
        __tablename__ = 'studentbasic'
        """表名"""
    
        id = Column(Integer, primary_key=True)
        studentName = Column(String(10))
        """学生姓名,限10个字符串"""
        cardId = Column(String(18))
        """身份证号,限18个字符串"""
        sYear = Column(Integer)
        """入学年度,纯数字"""
        sClass = Column(Integer)
        """班级,纯数字"""
        sex = Column(String(2))
        """性别,字符串类型"""
        studyNo = Column(String(25))
        """学号"""
    StudentEntity

    下面是DbFactory用于连接数据库(本例为Sqlite3数据库),生成Session:

    class DbFactory(object):
        """数据库连接工厂类"""
    
        def __init__(self):
            """ 初始化,类私有变量session和engine初始化为NONE,后调用init_db方法。 """
            self.session = None
            self.engine = None
            self.init_db()
    
        def init_db(self, path="data.db"):
            """设置engine
            :param path 字符串,设置数据文件位置,默认tools目录下的data.db
            :return 无
            """
            self.engine = create_engine('sqlite:///' + path, echo=True)
    
        def get_session(self):
            """获得session,如果self.engine没有初始化,调用init_db方法,如果已经初始化检查self.session是否有值,没有获取,有则返回
            :return: Session()实例,每个DbFactory的引用保持一个Session()实例。
            """
            if self.engine is None:
                self.init_db()
            Session = sessionmaker(bind=self.engine)
            if self.session is None:
                self.session = Session()
            return self.session
    
        def create_db(self):
            """ 初始化数据库表,用于正式使用软件以前初始化数据库。
            :return 无
            """
            Base.metadata.create_all(self.engine)
    DbFactory

    最后是DaoBase实现:

    class DaoBase(object, metaclass=abc.ABCMeta):
        """MVC中M层基类,在类中描述公共抽象方法"""
    
        def __init__(self):
            """初始化,引入DbFactory实例,并初始备用
            :return 无
            """
            self.dbfactory = DbFactory()
    
        @abc.abstractmethod
        def get_entityclass(self):
            """抽象方法,返回DAO维护的实体类,用于查询语句
            :return 类.class
            """
            pass
    
        def find_by_id(self, ids):
            """用ID查找
            :param ids 整数型
            :return 类实例
            """
            return self.dbfactory.get_session().query(self.get_entityclass()).filter(self.get_entityclass().id == ids).one()
    
        def create(self, obj):
            """存贮类实例至数据库
            :param obj 具体类实例
            :return 无
            """
            self.dbfactory.get_session().add(obj)
            self.dbfactory.get_session().commit()
    
        def update(self, obj):
            """
            更新数据,根据obj的ID查询数据库中的数据
            如果obj是利用session查询出来的,且和update使用同一个session,则没有变化中间的判断不会执行,这时已经修改过session中的数据直接commit
            如果obj只是保留id,自行定义的一个实例而非在同一个session中查询出来,则遍历实例中的所有属性(属性非以_开头)循环中会产生不一致的数据,
            利用setattr进行修改并更新,同样调用commit最终提交,所以下面这个commit必须执行。
            :param obj 修改后的实例
            :raise EntryNotFoundException 查询不到实例
            :raise ObjectNotMatchException obj与数据库查询的类不是同一种类
            :return 无
            """
            if isinstance(obj, self.get_entityclass()):
                try:
                    obj_saved = self.find_by_id(obj.id)
                    if obj_saved is None:
                        raise EntryNotFoundException()
                    for attribute_name in dir(obj_saved):
                        if attribute_name[0:1] != "_" and 
                                getattr(obj, attribute_name) != getattr(obj_saved, attribute_name):
                            setattr(obj_saved, attribute_name, getattr(obj, attribute_name))
                    self.__commit()
                except Exception as e:
                    raise e
            else:
                raise ObjectNotMatchException()
    
        def __commit(self):
            self.dbfactory.get_session().commit()
    
        @abc.abstractmethod
        def delete(self, obj):
            pass

    非常简单的实现,仅供娱乐。

  • 相关阅读:
    [C/C++]宽字符与控制台程序
    C# 实现屏幕键盘 (SCREENKEYBOARD)
    c#模拟键盘输入
    窗口玻璃特效,半透明窗口,使用DWM实现Aero Glass效果
    DMRS、DRS、SRS、CRS各自作用区别
    LTE的9种传输模式
    在4G通讯技术中什么是ZC根序列,ZC根序列规划的目的和原则是什么?
    為何LTE要先偵測PSS然後再偵測SSS 转自C114
    PSS和SSS用户小区接入的同步过程
    LTE PCI MOD3 规划
  • 原文地址:https://www.cnblogs.com/aocshallo1/p/13929235.html
Copyright © 2011-2022 走看看