简单ORM的实现
简单的orm实现
我们在使用各种框架的时候,关于数据库这方面的使用,框架给我们提供了很好的封装,这个就是orm
关系映射
orm的底层无非就是做了关系映射
数据库的表(table) --> 类(class)
记录(record,行数据)--> 对象(object)
字段(field)--> 对象的属性(attribute)
ORM设计
字段
首先是字段,每个字段都有很多的字段属性,然后考虑到,每个表的字段可能都不同,为了给他提供更好的拓展性,所以这里我们选择用类来封装
class Field(object):
def __init__(self, name, column_type, primary_key, default):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
class StringField(Field):
def __init__(self,name,
column_type='varchar=(255)',
primary_key=False,
default=None):
super().__init__(name,column_type,primary_key,default)
class IntegerField(Field):
def __init__(self,
name,
column_type='int',
primary_key=False,
default=None):
super().__init__(name, column_type, primary_key, default)
表
表有表名和字段信息等信息
class Teacher(Models):
print("teacher")
table_name='teacher'
tid = IntegerField(name='tid',primary_key=True)
tname = StringField(name='tname')
为了能更好的展示,dict数据类型更适合我们,所以最后让他继承dict,但是字典取值只能通过key取值,这样不方便,所以我们也要改写他的取值方式为.
取值
class Models(dict,metaclass=ModelMetaClass):
print("Models")
def __init__(self,**kwargs):
print(f'Models_init')
super().__init__(self,**kwargs)
def __getattr__(self, item):
return self.get(item,"没有该值")
def __setattr__(self, key, value):
self[key]=value
为了确保我们自己定义表的的时候不会有错误,我们需要加一步,字段的检测步骤,并对字段更好整理
class ModelMetaClass(type):
print("ModelMetaClass")
def __new__(cls,class_name,class_base,class_attrs):
print("ModelMetaClass_new")
#实例化对象的时候也会执行,我们要把这一次拦截掉
if class_name == 'Models':
#为了能让实例化顺利完成,返回一个空对象就行
return type.__new__(cls,class_name,class_base,class_attrs)
#获取表名
table_name = class_attrs.get('table_name',class_name)
#定义一个存主键的的变量
primary_key = None
#定义一个字典存储字段信息
mapping = {}
#name='tid',primary_key=True
#for来找到主键字段
for k,v in class_attrs.items():
#判断信息是否是字段
if isinstance(v,Field):
mapping[k] = v
#寻找主键
if v.primary_key:
if primary_key:
raise TypeError("主键只有一个")
primary_key=v.name
#将重复的键值对删除,因为已经放入了mapping
for k in mapping.keys():
class_attrs.pop(k)
if not primary_key:
raise TypeError("表必须要有一个主键")
class_attrs['table_name']=table_name
class_attrs['primary_key']=primary_key
class_attrs['mapping']=mapping
return type.__new__(cls,class_name,class_base,class_attrs)
数据库操作
数据库操作最好就是放在类里面,然后使用类方法
#查找
@classmethod
def select(cls,**kwargs):
ms=MySQL()
#如果没有参数默认是查询全部的
if not kwargs:
sql='select * from %s'%cls.table_name
res=ms.select(sql)
else:
k = list(kwargs.keys())[0]
v = kwargs.get(k)
sql='select * from %s where %s=?'%(cls.table_name,k)
#防sql注入
sql=sql.replace('?','%s')
res=ms.select(sql,v)
if res:
return [cls(**i) for i in res]
#新增
def save(self):
ms=MySQL()
#存字段名
fields=[]
#存值
values=[]
args=[]
for k,v in self.mapping.items():
#主键自增,不用给他赋值
if not v.primary_key:
fields.append(v.name)
args.append("?")
values.append(getattr(self,v.name))
sql = "insert into %s(%s) values(%s)"%(self.table_name,",".join(fields),",".join((args)))
sql = sql.replace('?','%s')
ms.execute(sql,values)
def update(self):
ms = MySQL()
fields = []
valuse = []
pr = None
for k,v in self.mapping.items():
#获取主键值
if v.primary_key:
pr = getattr(self,v.name,v.default)
else:
fields.append(v.name+'=?')
valuse.append(getattr(self,v.name,v.default))
print(fields,valuse)
sql = 'update %s set %s where %s = %s'%(self.table_name,','.join(fields),self.primary_key,pr)
sql = sql.replace('?',"%s")
ms.execute(sql,valuse)
Mysql连接
import pymysql
class MySQL:
#单例模式
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self):
self.mysql = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
database='orm_demo',
password='root',
charset='utf8',
autocommit=True
)
#获取游标
self.cursor = self.mysql.cursor(
pymysql.cursors.DictCursor
)
#查看
def select(self,sql,args=None):
#提交sql语句
self.cursor.execute(sql,args)
#获取查询的结果
res = self.cursor.fetchall()
return res
#提交
def execute(self,sql,args):
#提交语句可能会发生异常
try:
self.cursor.execute(sql,args)
except Exception as e:
print(e)
def close(self):
self.cursor.close()
self.mysql.close()
整体代码部分
MySQL.py
import pymysql
class MySQL:
#单例模式
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self):
self.mysql = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
database='orm_demo',
password='root',
charset='utf8',
autocommit=True
)
#获取游标
self.cursor = self.mysql.cursor(
pymysql.cursors.DictCursor
)
#查看
def select(self,sql,args=None):
#提交sql语句
self.cursor.execute(sql,args)
#获取查询的结果
res = self.cursor.fetchall()
return res
#提交
def execute(self,sql,args):
#提交语句可能会发生异常
try:
self.cursor.execute(sql,args)
except Exception as e:
print(e)
def close(self):
self.cursor.close()
self.mysql.close()
orm.py
from MySQL import MySQL
# 定义字段类
class Field(object):
def __init__(self, name, column_type, primary_key, default):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
class StringField(Field):
def __init__(self,name,
column_type='varchar=(255)',
primary_key=False,
default=None):
super().__init__(name,column_type,primary_key,default)
class IntegerField(Field):
def __init__(self,
name,
column_type='int',
primary_key=False,
default=None):
super().__init__(name, column_type, primary_key, default)
class ModelMetaClass(type):
print("ModelMetaClass")
def __new__(cls,class_name,class_base,class_attrs):
print("ModelMetaClass_new")
#实例化对象的时候也会执行,我们要把这一次拦截掉
if class_name == 'Models':
#为了能让实例化顺利完成,返回一个空对象就行
return type.__new__(cls,class_name,class_base,class_attrs)
#获取表名
table_name = class_attrs.get('table_name',class_name)
#定义一个存主键的的变量
primary_key = None
#定义一个字典存储字段信息
mapping = {}
#name='tid',primary_key=True
#for来找到主键字段
for k,v in class_attrs.items():
#判断信息是否是字段
if isinstance(v,Field):
mapping[k] = v
#寻找主键
if v.primary_key:
if primary_key:
raise TypeError("主键只有一个")
primary_key=v.name
#将重复的键值对删除,因为已经放入了mapping
for k in mapping.keys():
class_attrs.pop(k)
if not primary_key:
raise TypeError("表必须要有一个主键")
class_attrs['table_name']=table_name
class_attrs['primary_key']=primary_key
class_attrs['mapping']=mapping
return type.__new__(cls,class_name,class_base,class_attrs)
class Models(dict,metaclass=ModelMetaClass):
print("Models")
def __init__(self,**kwargs):
print(f'Models_init')
super().__init__(self,**kwargs)
def __getattr__(self, item):
return self.get(item,"没有该值")
def __setattr__(self, key, value):
self[key]=value
#查找
@classmethod
def select(cls,**kwargs):
ms=MySQL()
#如果没有参数默认是查询全部的
if not kwargs:
sql='select * from %s'%cls.table_name
res=ms.select(sql)
else:
k = list(kwargs.keys())[0]
v = kwargs.get(k)
sql='select * from %s where %s=?'%(cls.table_name,k)
#防sql注入
sql=sql.replace('?','%s')
res=ms.select(sql,v)
if res:
return [cls(**i) for i in res]
#新增
def save(self):
ms=MySQL()
#存字段名
fields=[]
#存值
values=[]
args=[]
for k,v in self.mapping.items():
#主键自增,不用给他赋值
if not v.primary_key:
fields.append(v.name)
args.append("?")
values.append(getattr(self,v.name))
sql = "insert into %s(%s) values(%s)"%(self.table_name,",".join(fields),",".join((args)))
sql = sql.replace('?','%s')
ms.execute(sql,values)
def update(self):
ms = MySQL()
fields = []
valuse = []
pr = None
for k,v in self.mapping.items():
#获取主键值
if v.primary_key:
pr = getattr(self,v.name,v.default)
else:
fields.append(v.name+'=?')
valuse.append(getattr(self,v.name,v.default))
print(fields,valuse)
sql = 'update %s set %s where %s = %s'%(self.table_name,','.join(fields),self.primary_key,pr)
sql = sql.replace('?',"%s")
ms.execute(sql,valuse)
class Teacher(Models):
print("teacher")
table_name='teacher'
tid = IntegerField(name='tid',primary_key=True)
tname = StringField(name='tname')
if __name__ == '__main__':
# tea=Teacher(tname="haha")
tea2=Teacher(tname="haha",tid=5)
# print(Teacher.select(tid=1))
# Teacher.save(tea)
print(Teacher.update(tea2))
简单ORM的实现的更多相关文章
- 简单ORM工具的设计和编写,自己项目中曾经用过的
http://www.cnblogs.com/szp1118/archive/2011/03/30/ORM.html 在之前的一个项目中自己编写了一个简单的ORM小工具,这次重新整理和重构了一下代码, ...
- iOS:Core Data 中的简单ORM
我们首先在xcdatamodel文件中设计我们的数据库:例如我建立一个Data的实体,里面有一个String类型的属性name以及一个Integer类型的num: 然后选中Data,添加文件,选择NS ...
- java基础强化——深入理解java注解(附简单ORM功能实现)
目录 1.什么是注解 2. 注解的结构以及如何在运行时读取注解 2.1 注解的组成 2.2 注解的类层级结构 2.3 如何在运行时获得注解信息 3.几种元注解介绍 3.1 @Retention 3.2 ...
- 实现简单ORM案例
ORM框架: • 我们希望设计一个可以实现对象和SQL自动映射的框架,但是整体用法和设计比Hibernate简单.砍掉不必要的功能.• 会穿插使用设计模式• 增加 – 将对象对应成sql语句,执行sq ...
- 封装JDBC:实现简单ORM框架lfdb
作者:Vinkn 来自http://www.cnblogs.com/Vinkn/ 一.简介 框架就是一组可重用的构件,LZ自己写的姑且就叫微型小框架:lfdb.LZ也对其他的ORM框架没有什么了解,现 ...
- JAVA描述的简单ORM框架
抽了点时间自己写了个ORM,主要是为了复习JAVA泛型,映射,注解方面的知识.如需代码,可前往:https://github.com/m2492565210/java_orm自行下载 框架的类结构如下 ...
- JDBC 利用反射技术将查询结果封装为对象(简单ORM实现)
ORM(Object Relational Mapping)对象关系映射 public class ORMTest { public static void main(String[] args) t ...
- python-元类和使用元类实现简单的ORM
元类 面向对象中,对象是类的实例,即对象是通过类创建出来的,在python中,一切皆对象,同样,类也是一个对象,叫做类对象,只是这个类对象拥有创建其子对象(实例对象)的能力.既然类是对象,那么类是通过 ...
- 终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了
前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...
随机推荐
- winform 数据库资料导出Excel方法(适用于资料数据较多加载慢,不用呈现至DatagridView)
Private Sub savefile(ByVal dgv2 As DataTable) Dim app As Object = CreateObject("Excel.Applicati ...
- CMMS系统中的物联监测
有条件的设备物联后,可时实查看设备运行状态,如发现异常,可提前干预.
- Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go 的I/O 多路复用 netpoll),提供了 goroutine-per- ...
- CSPS模拟测试59
这场考得我心态爆炸......... 开场T1只会$n^{2}$,然后发现bfs时每个点只需要被更新一次,其他的更新都是没用的. 也就是说,我们可以只更新还没被更新的点? 于是我先YY了一个链表,发现 ...
- 实现两个数字的交换(C语言)
int num1=10; int num2=20; //1.简单的数学方法实现数字交换 num1=num1+num2;//num1=30 num2=num1-num2;//num2=10 num1=n ...
- win10 visual studio 2017环境中安装CUDA8
从https://developer.nvidia.com/cuda-toolkit-archive下载CUDA 8 安装 从https://developer.nvidia.com/gamework ...
- nyoj 274-正三角形的外接圆面积 (R = PI * a * a / 3)
274-正三角形的外接圆面积 内存限制:64MB 时间限制:1000ms 特判: No 通过数:14 提交数:22 难度:0 题目描述: 给你正三角形的边长,pi=3.1415926 ,求正三角形的外 ...
- VLAN实验(1)Access接口
1.选择两台S3700的交换机,5台PC机,并按照下图链接好并填写IP,完成此拓扑图 2.由于现在我们还没有划分VLAN,这5台PC,还在同一个VLAN中,现在我们启动所有的设备,这是所有的主机应该是 ...
- Pashmak and Buses(构造)
题目链接:http://codeforces.com/problemset/problem/459/C 题意:n个人, k辆车, d天,每天将所有 任意人安排到k辆车, 问怎样安排, 可时不存在 2人 ...
- php5.6开启curl
1. 打开php安装目录,打开ext目录,是否有php_curl.dll扩展文件,如果没有该扩展文件,请在网上下载此文件. 2. 打开php.ini,找到 ;extension=php_cu ...