文档章节

SqlAlchemy个人学习笔记完整汇总

lemonwater
 lemonwater
发布于 2017/09/08 15:07
字数 3140
阅读 30
收藏 1
点赞 0
评论 0

使用 sqlalchemy 有3种方式:
方式1, 使用raw sql; 
方式2, 使用SqlAlchemy的sql expression; 
方式3, 使用ORM.  
前两种方式可以统称为 core 方式. 本文讲解 core 方式访问数据库, 不涉及 ORM. 

对于绝大多数应用, 推荐使用 SqlAlchemy. 即使是使用raw sql, SqlAlchemy 也可以带来如下好处: 
1. 内建数据库连接池. [注意]如果是sqlalchemy+cx_oracle的话, 需要禁掉 connection pool, 否则会有异常. 方法是设置sqlalchemy.poolclass为sqlalchemy.pool.NullPool
2. 强大的log功能
3. 数据库中立的写法, 包括: sql参数写法, limit语法
4. 特别提一下, where()条件的==your_value, 如果your_value等于None, 真正的Sql会转为Is None

SqlAlchemy的sql expression和raw sql的比较:
1. sql expression 写法是纯python代码, 阅读性更好, 尤其是在使用insert()方法时, 字段名和取值成对出现.  
2. raw sql 比 sql expression 更灵活, 如果SQL/DDL很复杂, raw sql就更有优势了. 

==============================
sqlalchemy 超简单教程
==============================
http://solovyov.net/en/2011/04/23/basic-sqlalchemy/
http://flask.pocoo.org/docs/patterns/sqlalchemy/#sql-abstraction-layer
http://www.blog.pythonlibrary.org/2010/09/10/sqlalchemy-connecting-to-pre-existing-databases/
http://www.blog.pythonlibrary.org/2010/02/03/another-step-by-step-sqlalchemy-tutorial-part-1-of-2/
http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html
http://mapfish.org/doc/tutorials/sqlalchemy.html
sqlalchemy 官网的pdf文档, 可以作为 reference 使用


==============================
常用的数据库连接字符串
==============================
#sqlite
sqlite_db = create_engine('sqlite:////absolute/path/database.db3')
sqlite_db = create_engine('sqlite://')  # in-memory database
sqlite_db = create_engine('sqlite:///:memory:') # in-memory database
# postgresql
pg_db = create_engine('postgres://scott:tiger@localhost/mydatabase')
# mysql
mysql_db = create_engine('mysql://scott:tiger@localhost/mydatabase')
# oracle
oracle_db = create_engine('oracle://scott:tiger@127.0.0.1:1521/sidname')
# oracle via TNS name
oracle_db = create_engine('oracle://scott:tiger@tnsname')
# mssql using ODBC datasource names.  PyODBC is the default driver.
mssql_db = create_engine('mssql://mydsn')
mssql_db = create_engine('mssql://scott:tiger@mydsn')
# firebird
firebird_db = create_engine('firebird://scott:tiger@localhost/sometest.gdm')

==============================
关于一些非主流数据库缺少DB API接口的问题
==============================
比如teradata, 没有专门的DB API实现, 但 odbc driver肯定会提供的, 否则就无法在江湖上混了. pypyodbc + ODBC driver 应该是一个选项. pypyodbc 和 pyodbc接口一致, 同时它是纯 python实现, 理论上应该支持 python/ironpython/jython. 另外, 我猜想sqlalchemy应该能基于这一组合访问所有的数据库, 待验证. 
 pypyodbc 主页:  http://code.google.com/p/pypyodbc/


==============================
#connnectionless执行和connnection执行
==============================
1. 直接使用engine执行sql的方式, 叫做connnectionless执行, 
2. 先使用 engine.connect()获取conn, 然后通过conn执行sql, 叫做connection执行
如果要在transaction模式下执行, 推荐使用connection方式, 如果不涉及transaction, 两种方法效果是一样的. 

==============================
#sqlalchemy推荐使用text()函数封装一下sql字符串
==============================
好处巨多:
1. 不同数据库, 可以使用统一的sql参数传递写法. 参数须以:号引出. 在调用execute()的时候, 使用dict结构将实参传进去. 
    from sqlalchemy import text
    result = db.execute(text('select * from table where id < :id and typeName=:type'), {'id': 2,'type':'USER_TABLE'})
2. 如果不指定parameter的类型, 默认为字符串类型; 如果要传日期参数, 需要使用text()的bindparams参数来声明
    from sqlalchemy import DateTime
    date_param=datetime.today()+timedelta(days=-1*10)
    sql="delete from caw_job_alarm_log  where alarm_time<:alarm_time_param"
    t=text(sql, bindparams=[bindparam('alarm_time_param', type_=DateTime, required=True)])
    db.execute(t,{"alarm_time_param": date_param})    
    
    参数bindparam可以使用type_来指定参数的类型, 也可以使用 initial 值来指定参数类型
        bindparam('alarm_time_param', type_=DateTime) #直接指定参数类型
        bindparam('alarm_time_param', DateTime()) #使用初始值指定参数类型
3. 如要转换查询的结果中的数据类型, 可以通过text()的参数typemap参数指定. 这点比mybatis还灵活,
        t = text("SELECT id, name FROM users",
                typemap={
                    'id':Integer,
                    'name':Unicode
                }
        )
4. 还有其他, 详见sqlalchemy\sql\expression.py中的docstring. 


==============================
#sqlalchemy访问数据库的示例
==============================
#-----------------------------------
#获取数据库
#-----------------------------------
from sqlalchemy import create_engine
db=create_engine("sqlite:///:memory:", echo=True)


#-----------------------------------
#DDL
#-----------------------------------
db.execute("create table users(userid char(10), username char(50))")


#-----------------------------------
#DML
#-----------------------------------
resultProxy=db.execute("insert into users (userid,username) values('user1','tony')")
resultProxy.rowcount  #return rows affected by an UPDATE or DELETE statement


#-----------------------------------
#Query
#-----------------------------------
resultProxy=db.execute("select * from users")
resultProxy.close(), resultProxy 用完之后, 需要close
resultProxy.scalar(), 可以返回一个标量查询的值
ResultProxy 类是对Cursor类的封装(在文件sqlalchemy\engine\base.py),
ResultProxy 类有个属性cursor即对应着原来的cursor.
ResultProxy 类有很多方法对应着Cursor类的方法, 另外有扩展了一些属性/方法.
resultProxy.fetchall()
resultProxy.fetchmany()
resultProxy.fetchone()
resultProxy.first()
resultProxy.scalar()
resultProxy.returns_rows  #True if this ResultProxy returns rows.
resultProxy.rowcount  #return rows affected by an UPDATE or DELETE statement. It is not intended to provide the number of rows present from a SELECT.

****遍历ResultProxy时, 得到的每一个行都是RowProxy对象, 获取字段的方法非常灵活, 下标和字段名甚至属性都行. rowproxy[0] == rowproxy['id'] == rowproxy.id, 看得出 RowProxy 已经具备基本 POJO 类特性.  


#-----------------------------------
#使用transaction
#-----------------------------------
#SqlAlchemy支持支持事务, 甚至事务可以嵌套. 缺省事务是自动提交,即执行一条SQL就自动提交。

#-如果更精准地控制事务, 最简单的方法是使用 connection, 然后通过connection获取transaction对象
connection = db.connect()
trans = connection.begin()
try:
    dosomething(connection)
    trans.commit()
except:   
    trans.rollback()

#-还有一种方式是,在创建engine时指定strategy='threadlocal'参数,这样会自动创建一个线程局部的连接,对于后续的无连接的执行都会自动使用这个连接,这样在处理事务时,只要使用 engine 对象来操作事务就行了。如:
#参见 http://hi.baidu.com/limodou/blog/item/83f4b2194e94604043a9ad9c.html
db = create_engine(connection, strategy='threadlocal')
db.begin()
try:
    dosomething()
except:
    db.rollback()
else:
    db.commit()
    

#-缺省事务是自动提交,即执行一条SQL就自动提交. 也可以在connection和statement上通过execution_options()方法修改为手动commit模式
conn.execution_options(autocommit=False)
设置为手动提交模式后, 要提交, 需要调用conn.commit()



#-----------------------------------
#如何使用 pyDbRowFactory
#-----------------------------------
#pyDbRowFactory是我开发的一个通用RowFactory, 可以绑定cursor和你的 model pojo 类, 新版本的pyDbRowFactoryResultProxy. 下面示例是pyDbRowFactory的最基本用法
#方法1, 使用 cursor对象
cursor=resultProxy.cursor
from pyDbRowFactory import DbRowFactory
rowFactory=DbRowFactory(cursor, "your_module.your_row_class") 
lst=factory.fetchAllRowObjects()

#方法2, 直接使用 resultProxy
from pyDbRowFactory import DbRowFactory 
factory=DbRowFactory.fromSqlAlchemyResultProxy(resultProxy, "your_module.your_row_class")
lst=factory.fetchAllRowObjects()
        
前面讲过, SQLAlchemy使用 ResultProxy封装了cursor, ResultProxy的每一个行记录是一个RowProxy 类对象. RowProxy 使用起来非常方便,  对于查询select userName from users,  
每一个行结果都可以使用rowproxy来访问, 写法相当灵活.  rowproxy.userName=rowproxy["userName"]==rowproxy[0], 所以有了RowProxy,  很多时候, 没有必要再为每个表创建一个 model pojo 类.  



#-----------------------------------
#连接池
#-----------------------------------
sqlalchemy 默认的连接池算法选用规则为:
1.连接内存中的sqlite, 默认的连接池算法为 SingletonThreadPool 类, 即每个线程允许一个连接
2.连接基于文件的sqlite, 默认的连接池算法为 NullPool 类, 即没有连接池
3.对于其他情况, 默认的连接池算法为 QueuePool 类
当然, 我们也可以实现自己的连接池算法, 
db = create_engine('sqlite:///file.db', poolclass=YourPoolClass)
create_engine()函数和连接池相关的参数有:
-pool_recycle, 默认为-1, 推荐设置为7200, 即如果connection空闲了7200秒, 自动重新获取, 以防止connection被db server关闭. 
-pool_size=5, 连接数大小,默认为5,正式环境该数值太小,需根据实际情况调大
-max_overflow=10, 超出pool_size后可允许的最大连接数,默认为10, 这10个连接在使用过后, 不放在pool中, 而是被真正关闭的. 
-pool_timeout=30, 获取连接的超时阈值, 默认为30秒



#-----------------------------------
#log输出
#-----------------------------------
--如果只需在sys.stdout输出, 用不着引用 logging 模块就能实现
db = create_engine('sqlite:///file.db', echo=True)

--如果要在文件中输出, log文件不具备rotate功能, 不推荐在生产环境中使用. 
import logging
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

   
#-----------------------------------
#使用 sqlalchemy core 的最佳实践
#-----------------------------------
我不太喜欢使用ORM方式, 主要是ORM学习成本比较高, 另外, 构建复杂的查询也比较困难. 更多的时候是使用raw sql和sql expression方法. 
1. declarative 是 SqlAlchemy的一个新的扩展, 只能用在 ORM 中, 不能用在SQL Expression中
2. 如果要使用ORM时, table必须有主键; 使用 raw sql和sql expression, 没有这个约束.

使用心得: 
1. 查询不管是否复杂, 直接使用 raw sql; 增删改多是单表操作, 使用sql expression 就足够了. 
2. 具体讲, 对于增删改, 比如一个User类, 可包含一个固定的 _table 的成员, _table=Table('users', metadata, autoload=True), 增删改直接使用_table对象来完成.
3. 对于查询, 若结果集能映射到一个实体对象, 使用pyDbRowFactory完成对象实例化. 若结果集涉及多个实体, 直接使用ResultProxy, ResultProxy的每一行对象也具有基本的对象特征, 多数情况下没有必要再专门映射成一个特别的类. 
4. 表之间关系的处理, 比如: users 表和 addresses 表, 存在 1:n的关系, 对应地, User 类也会有个AddressList的成员, 在实体化一个User对象后, 我们可立即查询 addresses 表, 获取该用户的address列表, 分2步就可以完成这种1:n的关系映射.


使用 sqlalchemy 的写法太灵活了, 下面仅仅是我喜欢的一种写法, 仅仅从排版看, 就相当漂亮.
构建insert语句: _table.insert().values(f1=value1,f2=value2,)
构建update语句: _table.update().values(f1=newvalue1,f2=newvalue2).where(_table.c.f1==value1).where(_table.c.f2==value2)
构建delete语句: _table.delete().where(_table.c.f1==value1).where(_table.c.f2==value2)
批量insert/update/delete, 将每行数据组成一个dict, 再将这些dict组成一个list, 和_table.insert()/update()/delete()一起作为参数传给 conn.execute(). 
    conn.execute(_table.insert(), [
    {’user_id’: 1, ’email_address’ : ’jack@yahoo.com’},
    {’user_id’: 1, ’email_address’ : ’jack@msn.com’},
    {’user_id’: 2, ’email_address’ : ’www@www.org’},
    {’user_id’: 2, ’email_address’ : ’wendy@aol.com’},
    ])
sql expression 也可以像raw sql的text函数一样使用bindparam, 方法是, 在调用insert()/update()/delete()时声明参数, 然后在conn.execute()执行时候, 将实参传进去. 
    d=_table.delete().where(_table.c.hiredate<=bindparam("hire_day",DateTime(), required=True))
    conn.execute(d, {"hire_day":datetime.today()})
    

 
where()和ORM中的filter()接受的参数是一样, 各种SQL条件都支持. 
#equals:
where(_table.c.name == ’ed’)
#not equals:
where(_table.c.name != ’ed’)
#LIKE:
where(_table.c.name.like(’%ed%’))
#IN:
where(_table.c.name.in_([’ed’, ’wendy’, ’jack’]))
#NOT IN:
where(~_table.c.name.in_([’ed’, ’wendy’, ’jack’]))
#IS NULL:
where(_table.c.name == None)
#IS NOT NULL:
where(_table.c.name != None)
#AND:
from sqlalchemy import and_
where(and_(_table.c.name == ’ed’, _table.c.fullname == ’Ed Jones’))
#AND也可以通过多次调用where()来实现
where(_table.c.name == ’ed’).where(_table.c.fullname == ’Ed Jones’)
#OR:
from sqlalchemy import or_
where(or_(_table.c.name == ’ed’, _table.c.name == ’wendy’))
#match: The contents of the match parameter are database backend specific.
where(_table.c.name.match(’wendy’))


--==========================
--python file: mydatabase.py
--==========================
from sqlalchemy import create_engine 
from sqlalchemy.schema import MetaData
 
#db = create_engine('sqlite:///:memory:',  echo=True)
db = create_engine('sqlite:///c://caw.sqlite.db',  echo=True)
metadata = MetaData(bind=db) 


--==========================
--python file: dal.py 
--==========================
from sqlalchemy.sql.expression import text, bindparam
from sqlalchemy.sql import select,insert, delete, update
from sqlalchemy.schema import Table
    
from mydatabase import db,metadata
from pyDbRowFactory import DbRowFactory    
    
class caw_job(object):
    FULL_NAME="dal.caw_job"
    tablename="caw_job"
    _table=Table(tablename, metadata, autoload=True)
    
    def __init__(self):
        self.app_domain       =None
        self.job_code         =None
        self.job_group        =None 
        self.cron_year        =None
        self.cron_month       =None
        self.cron_day         =None
        self.cron_week        =None
        self.cron_day_of_week =None
        self.cron_hour        =None
        self.cron_minute      =None
        self.description      =None 
 
    @classmethod    
    def getEntity(cls, app_domain, jobCode):
        sql="select * from caw_job where app_domain=:app_domain and job_code=:job_code";
        resultProxy=db.execute(text(sql),{'app_domain':app_domain,
                                          'job_code':jobCode})
        DbRowFactory.fromSqlAlchemyResultProxy(resultProxy, cls.FULL_NAME)
        return DbRowFactory.fetchOneRowObject()
    
    
    def insert(self):
        i=self._table.insert().values(
                                      app_domain      =self.app_domain      ,     
                                      job_code        =self.job_code        ,
                                      job_group       =self.job_group       ,
                                      cron_year       =self.cron_year       ,
                                      cron_month      =self.cron_month      ,
                                      cron_day        =self.cron_day        ,
                                      cron_week       =self.cron_week       ,
                                      cron_day_of_week=self.cron_day_of_week,
                                      cron_hour       =self.cron_hour       ,
                                      cron_minute     =self.cron_minute     ,
                                      description     =self.description     ,                                      
                                      ) 
        db.execute(i)
    
    def update(self):
        u=self._table.update().values(
                                      app_domain       =self.app_domain       ,     
                                      job_code         =self.job_code         ,
                                      job_group        =self.job_group        ,
                                      cron_year        =self.cron_year        ,
                                      cron_month       =self.cron_month       ,
                                      cron_day         =self.cron_day         ,
                                      cron_week        =self.cron_week        ,
                                      cron_day_of_week =self.cron_day_of_week ,
                                      cron_hour        =self.cron_hour        ,
                                      cron_minute      =self.cron_minute      ,
                                      description      =self.description      ,                ,                                         
                                      ).where(self._table.c.app_domain==self.app_domain)\
                                      .where(self._table.c.job_code==self.job_code)
        db.execute(u)
        
        
    def delete(self):
        d=self._table.delete().where(self._table.c.app_domain==self.app_domain)\
         .where(self._table.c.job_code==self.job_code)
        db.execute(d)

            

    
#-----------------------------------
#使用sqlalchemy.ext.declarative 来生成表, 所有的表都必须有主键.
#在系统初期, 数据模型往往需要经常调整, 使用这种方式修改表结构更方便些.
#-----------------------------------
--python file: models.py
from sqlalchemy import create_engine 
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String , Boolean, DateTime, Float

engine = create_engine('sqlite:///:memory:',  echo=True)
Base = declarative_base()

#  ddl_caw_job 是专门用来生成数据库对象的, 没有其他用处    
class ddl_caw_job(Base): 
    __tablename__="caw_job"
    job_name   =Column(String(200), primary_key=True)
    job_group  =Column(String(200))
        
def init_db():
    Base.metadata.create_all(bind=engine,)    

  • 联合查询---join的使用:
order_receiver_list = query.join(ZsConsumerUserDo, ZsOrderDo.user_id == ZsConsumerUserDo.id).filter(
    ZsConsumerUserDo.phone.ilike('%' + keywords + '%')).filter(ZsOrderDo.deleted == 0).all()

http://www.jb51.net/article/49789.htm

  • 多表联合查询、搜索、去重、分页功能实现
def get_order_by_conditions(self, page_no, page_size, keywords,status):

    """"
    @:return 返回根据keywords查询到的所有对象
    """
    page_query = PageQuery(page_no, page_size)
    if status == 8:
        query = self.db.query(distinct(ZsOrderDo.order_no), ZsOrderDo)
    else:
        query = self.db.query(distinct(ZsOrderDo.order_no), ZsOrderDo).filter(ZsOrderDo.status == status)
    # 根据订单号查询
    order_no_list = query.filter(ZsOrderDo.order_no.ilike('%' + str(keywords) + '%')).filter(
        ZsOrderDo.deleted == 0)
    # 根据活动名称查询
    order_event_list = query.join(ZsEventDo, ZsOrderDo.event_id == ZsEventDo.id).filter(
        ZsEventDo.name.ilike('%' + str(keywords) + '%')).filter(ZsOrderDo.deleted == 0)
    # 根据购买者查询
    order_receiver_list = query.join(ZsConsumerUserDo, ZsOrderDo.user_id == ZsConsumerUserDo.id).filter(
        ZsConsumerUserDo.phone.ilike('%' + str(keywords) + '%')).filter(ZsOrderDo.deleted == 0)
    # 根据地址查询(物流)
    order_wuliu_address_list = query.filter(ZsOrderDo.receiver_address.ilike('%' + str(keywords) + '%')).filter(
        ZsOrderDo.deleted == 0)
    # 根据地址查询(自提)
    order_ziti_address_list = query.join(ZsAddressDo, ZsOrderDo.address_id == ZsAddressDo.id).filter(
        ZsAddressDo.address.ilike('%' + str(keywords) + '%')).filter(ZsOrderDo.deleted == 0)
    # 根据商家名称查询
    order_merchant_list = query.join(ZsMerchantDo, ZsOrderDo.merchant_id == ZsMerchantDo.id).filter(
        ZsMerchantDo.name.ilike('%' + str(keywords) + '%')).filter(ZsOrderDo.deleted == 0)
    # 根据群名称查询
    order_group_list = query.join(ZsGroupDo, ZsOrderDo.group_id == ZsGroupDo.id).filter(
        ZsGroupDo.name.ilike('%' + str(keywords) + '%')).filter(ZsOrderDo.deleted == 0)
    # 根据付款金额查询
    order_payment_list = query.filter(ZsOrderDo.payment.ilike('%' + str(keywords) + '%')).filter(
        ZsOrderDo.deleted == 0)
    # 根据订单状态查询
    order_status_list = query.filter(ZsOrderDo.status == keywords).filter(
        ZsOrderDo.deleted == 0)
    # 根据配送方式查询
    order_receiver_type_list = query.filter(ZsOrderDo.receive_type == int(keywords)).filter(
        ZsOrderDo.deleted == 0)
    # 根据创建时间查询
    order_gmt_created_list = query.filter(ZsOrderDo.gmt_created.ilike('%' + str(keywords) + '%')).filter(
        ZsOrderDo.deleted == 0)
    query2 = order_no_list.union(order_event_list).union(order_receiver_list).union(order_wuliu_address_list) \
        .union(order_ziti_address_list).union(order_merchant_list).union(order_group_list).union(order_payment_list) \
        .union(order_status_list).union(order_gmt_created_list).union(order_receiver_type_list)
    result_lenght = len(query2.all())
    result = query2.slice(page_query.start_row, page_query.end_row).all()
    return result, result_lenght

本文转载自:http://www.cnblogs.com/harrychinese/archive/2012/09/12/My_Own_Tutorial_For_SqlAlchemy.html

共有 人打赏支持
lemonwater
粉丝 2
博文 60
码字总数 6420
作品 0
西安
[flask-SQLAlchemy]关于flask-SQLAlchemy的初级使用教程

鉴于网上关于flask-SQLAlchemy的实例使用教程参差不齐,于此写下工作学习过程中的使用过程,以便分享交流。 对于python关于flask有一定了解的高端玩家来说,请转至flask官方开发文档。 一.安...

yzy121403725 ⋅ 05/24 ⋅ 0

ORM、SQLAlchemy数据库操作

ORM介绍 背景: 用底层的sql写的话,相当于通过pymysql 游标的方式连接“http://blog.51cto.com/jacksoner/2113454 ”,为了避免把sql语句写死在代码里,有没有一种方法直接把原生sql封装好了...

jiekegz ⋅ 05/11 ⋅ 0

flask_sqlalchemy简单用法

说明   SQLAlchemy 是 Python 的 ORM 框架,它的理念是:数据库的量级和性能重要于对象集合,而对象集合的抽象又重要于表和行 1、安装 2.2、创建表文件

812374156 ⋅ 05/18 ⋅ 0

SQLAlchemy 学习(一)

最近用到比较多的Python,当然访问数据库不能用原生的模块直接写Sql语句,这样太累。找了一本SQLAlchemy的教材来研究,记下学习笔记把。 相关的代码的例子在: https://github.com/DoubleSpo...

lemonwater ⋅ 05/14 ⋅ 0

慕课网Flask高级编程实战-9.书籍交易模型(数据库事务、重写Flask中的对象)

9.1 鱼豆 我们的鱼书有一个经济系统,在上传一本书的时候,将获取0.5个鱼豆。赠送一个本书的时候,再获取1个鱼豆。索要一本书的时候,消耗一个鱼豆,其中赠送和索要书籍是用户之间鱼豆互相加...

Meet相识_bfa5 ⋅ 06/14 ⋅ 0

Python的Flask框架中前端通过筛选添加动态排序功能

使用flask框架的时,前端通过使用bootstrap的form结构添加多选功能,使用多选的选择时候返回一个筛选后的结果,这样想对结果排序就需要动态排序功能 方法一: 在SQL中非常简单,即语句SELECT ...

走马兰台 ⋅ 05/25 ⋅ 0

SQLAlchemy技术文档(中文版)(全)

原文链接:http://www.cnblogs.com/iwangzc/p/4112078.html(感谢作者的分享) https://blog.csdn.net/Lotfee/article/details/57406450(感谢作者的分享) sqlalchemy 官方文档:http://do......

shangshanyang ⋅ 05/27 ⋅ 0

SQLAlchemy 1.2.7 发布,Python 的 ORM 框架

SQLAlchemy 1.2.7 已发布,引入了一系列针对 Core 和 ORM 的修复: [orm] [bug] Fixed regression in 1.2 within sharded query feature where the new “identity_token” element was not ......

王练 ⋅ 04/21 ⋅ 0

慕课网Flask高级编程实战-3.蓝图、模型与CodeFirst

3.1 应用、蓝图与视图函数 1.Flask的层级关系 Flask最上层是app核心对象 在这个核心对象上可以插入很多蓝图,这个蓝图是不能单独存在的,必须将app作为插板插入app 在每一个蓝图上,可以注册...

Meet相识_bfa5 ⋅ 06/04 ⋅ 0

CMS 内容管理框架 - PFCMS

PFCMS是一个免费开源的cms内容管理框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。PFCMS从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性...

@you ⋅ 06/19 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

服务网关过滤器

过滤器作用 我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了。但是,每个客户端用户请求微服务应用提供的接口时,它们的访问权限往往都需要有一定的限制,系统并不会...

明理萝 ⋅ 17分钟前 ⋅ 1

【2018.06.21学习笔记】【linux高级知识 14.1-14.3】

14.1 NFS介绍 NFS服务全称是NetWork File System:网络文件系统,最早有sun公司开发的,4.0版本由Netapp公司开发,是基于RPC远程过程调用(Remote Procedure Call)协议的服务。 14.2 NFS服务...

lgsxp ⋅ 26分钟前 ⋅ 0

Day18 vim编辑模式、命令模式与练习

编辑模式 命令模式 :nohl 不高亮显示 :x与:wq类似,如果在更改文件之后操作,两者效果一样;如果打开文件,没有任何操作; :wq会更改mtime,但是:x不会。 练习题 扩展 vim的特殊用法 ht...

杉下 ⋅ 29分钟前 ⋅ 0

Enum、EnumMap、EnumSet

1、Enum 不带参数 public enum Car { AUDI { @Override public int getPrice() { return 25000; } }, MERCEDES { ......

职业搬砖20年 ⋅ 30分钟前 ⋅ 0

Java中的锁使用与实现

1.Lock接口 锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。 在Lock出现之前,java程序是靠synchronized关键字实现锁功能的,而Java SE5之后,...

ZH-JSON ⋅ 31分钟前 ⋅ 0

线程组和 ThreadLocal

前言 在上面文章中,我们从源码的角度上解析了一下线程池,并且从其 execute 方法开始把线程池中的相关执行流程过了一遍。那么接下来,我们来看一个新的关于线程的知识点:线程组。 线程组 ...

猴亮屏 ⋅ 33分钟前 ⋅ 0

相对路径和绝对路径

基本概念   文件路径就是文件在电脑中的位置,表示文件路径的方式有两种,相对路径和绝对路径。在网页设计中通过路径可以表示链接,插入图像、Flash、CSS文件的位置。   物理路径:物理路...

临江仙卜算子 ⋅ 37分钟前 ⋅ 0

消息队列属性及常见消息队列介绍

什么是消息队列? 消息队列是在消息的传输过程中保存消息的容器,用于接收消息并以文件的方式存储,一个队列的消息可以同时被多个消息消费者消费。分布式消息服务DMS则是分布式的队列系统,消...

中间件小哥 ⋅ 39分钟前 ⋅ 0

java程序员使用web3j进行以太坊开发详解

如何使用web3j为Java应用或Android App增加以太坊区块链支持,教程内容即涉及以太坊中的核心概念,例如账户管理包括账户的创建、钱包创建、交易转账,交易与状态、智能合约开发与交互、过滤器...

笔阁 ⋅ 39分钟前 ⋅ 0

vim编辑模式、vim命令模式

vim编辑模式 使用vim filename 进入的界面是一般模式,在这个模式下虽然我们能够查看,复制,剪切,粘贴,但是不能编辑新的内容,如何能直接写入东西呢?这就需要进入编辑模式了,从一般模式...

李超小牛子 ⋅ 42分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部