最近在项目中用到了sqlalchemy,作为一名跳转到python开发中的新手,把sqlalchemy最近的一些使用心得记录下来。作为一名hibernate的移民很自然的想构建一个BaseDao。经过研究写出了一版简单的sqlalchemy版本的BaseDao。
class BaseDao(object):
def __init__(self, session, model):
self._sess = session
self._model = model
self._logger = logging.getLogger(__name__)
self._primary_key_group = inspect(self._model).primary_key
self._key_count = len(self._primary_key_group)
def add(self, model_dict):
new_model = self._get_model_obj(model_dict)
if new_model is None:
self._logger.error("Add data format error")
return None
self._sess.add(new_model)
success = self._flush()
if not success:
return None
else:
return self.__get_model_id(new_model)
def __get_model_id(self, model_obj):
if self._key_count == 1:
return getattr(model_obj, self._primary_key_group[0].name)
else:
key_tuple = ()
for key in self._primary_key_group:
value = getattr(model_obj, key.name)
key_tuple = key_tuple + (value,)
return key_tuple
def _flush(self):
try:
self._sess.flush()
except sqlalchemy.exc.OperationalError as e:
self._logger.error("flush sql failed, error info:{}".format(e.message))
return False
return True
具体代码如上(此处代码不全),这边主要利用Python能够将类作为参数传递的属性,实现了java中类似于泛型的功能,另外考虑到在构建数据表的过程中主键的形式多种多样,因此在add方法中利用反射获取主键返回,同时,对于联合主键的形式进行了支持。
在开发的过程中也遇到两个问题没有解决,在此提出来,如果有好的解决方法,欢迎指教。
(1) 想实现一个自定义查询条件的通用查询接口,利用
session.query(model).filter(conditon).all()
方法查询,但是没有弄清楚condition应该怎么进行传参。
(2) 第二个问题是关于事务边界控制的,在hibernate中可以通过配置文件控制事务的传播属性(propagation),如REQUIRES_NEW等等,这边需要控制session的commit时机,不知道在sqlalchemy中有没有很好的方法解决。