美文网首页数据库架构设计
数据库连接-静态构建表

数据库连接-静态构建表

作者: 架构师的一小步 | 来源:发表于2019-04-02 10:47 被阅读0次
    静态构建表-指手动创建数据库,自己写sql代码

    第一步:新建一个Connection类?
    作用:管理我们数据库
    功能:
    打开数据库
    关闭数据库
    执行SQL语句
    数据库基本属性使用(后面会用到)->铺垫

    第二步:定义数据库位置方式(类型)
    三种类型:内存数据库、临时数据库、URI方式(地址)
    枚举->Location
    三种数据库存储位置不同
    网址:https://www.sqlite.org/inmemorydb.html#sharedmemdb

    第三步:定义数据库SQL操作类(操作表)
    种类:
    插入数据-insert
    更新数据-update
    删除数据-delete
    枚举->定义表操作

    第四步:打开数据库
    通过构造方法实现

    第五步:检测数据库结果

    第六步:创建数据库执行队列
    数据库所有表操作->什么样队列中执行
    串行队列->一个个排队执行(线下买票)
    并行队列->同时执行(网上购票)
    问题:什么时候串行队列、什么时候并行队列?
    挖个坑?后面我们在讨论?

    第七步:执行SQL语句

    第八步:定义数据库基本操作属性
    1、关闭数据库
    2、数据库状态->是否是可读性数据库
    3、最后插入的一条数据所返回的行id->rowid
    4、数据库受影响行数->changes
    5、数据库自从打开到目前为止数据库受影响行数
    insert、delete、update总共操作几次
    insert->10次(插入10条数据)
    delete->删除5条->干坏事5次
    update->更新2次->干坏事2次
    总共:到目前为止17次
    6、中断任何长时间运行的查询操作(客户端少见)
    服务器开发->我开发服务器->100万数量级->耗费时间长
    7、数据库超时

    第九步:测试

    具体代码

    import UIKit
    import SQLite3
    
    //太监类
    //第一步:新建一个Connection类?
    public final class Connection {
    
    //   第二步:定义数据库位置方式(类型)->几种位置方式->指定存储位置
    //   三种类型:内存数据库、临时数据库、URI方式(地址)
    //   枚举->Location
        //网址:https://www.sqlite.org/inmemorydb.html#sharedmemdb
        public enum Location {
            //内存数据库->相当于->uri(":memory")
            case inMemory
            //临时数据库->相当于->uri("")
            case temporary
            //URI方式(地址)->相当于->uri("/user/test.db")
            case uri(String)
        }
      
    //    第三步:定义数据库SQL操作类(操作表)
    //    种类:
    //    插入数据-insert
    //    更新数据-update
    //    删除数据-delete
    //    枚举->定义表操作
        public enum Operation {
            //    插入数据-insert
            case insert
            //    更新数据-update
            case update
            //    删除数据-delete
            case delete
            //数据库类型转换
            fileprivate init(rawValue:Int32){
                switch rawValue {
                case SQLITE_INSERT:
                    self = .insert
                case SQLITE_UPDATE:
                    self = .update
                case SQLITE_DELETE:
                    self = .delete
                default:
                    fatalError("没有这个操作类型...")
                }
            }
        }
        
        
    //    第四步:打开数据库
    //    通过构造方法实现
        //第一个默认构造方法
        fileprivate var _handle: OpaquePointer? = nil
        public init(_ location: Location = .inMemory, readonly: Bool = false) throws {
            //打开数据库
            //参数一:数据位置
            //参数二:数据库指针(用于操作数据库)
            //参数三:打开数据库方式
            //SQLITE_OPEN_READONLY:只读数据库
            //SQLITE_OPEN_CREATE:创建数据库(没有就创建)
            //SQLITE_OPEN_READWRITE:可读可写数据库
            //SQLITE_OPEN_FULLMUTEX:设置数据库链接运行队列模式->串行队列、并行队列
            //支持多线程操作
            let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
            let result = sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil)
            //判定数据库是否成功状态(面向形式设计)
            //将result->变为对象->枚举->关心可选项
            //关心 = 1,0,-1->枚举->对象->代码阅读可读性高
            //检测数据库返回值
            try check(result)
            
            
            //第六步:定义队列->并行队列
            //主队列:串行队列
            //设置队列值(缓存当前Connaction所在的队列)
            queue.setSpecific(key: queueKey, value: queueContext)
        }
        
        //第二个默认构造方法
        //第二个构造方法调用第一个构造方法
        //普及一个语法->遍历构造器
        public convenience init(_ filename: String, readonly: Bool = false) throws {
            try self.init(.uri(filename), readonly: readonly)
        }
        
        
        //第五步:检测数据库结果
        //检测是否成功,还是失败
        //resultCode->数据库返回结果
        //throws->向外抛异常->客户端处理异常
        //大家都是用代码,很少自己写(成长很少)
        //第一次接触,蒙蔽很正常
        //相当于异常传递->事件传递
        @discardableResult func check(_ resultCode: Int32) throws -> Int32 {
            guard let error = Result(errorCode: resultCode, connection: self) else {
                return resultCode
            }
            //失败了->数据库打开失败了
            //抛异常(我不处理异常)
            throw error
        }
        
        
    //    第六步:创建数据库执行队列
    //    数据库所有表操作->什么样队列中执行
    //    串行队列->一个个排队执行(线下买票)
    //    并行队列->同时执行(网上购票)
    //    问题:什么时候串行队列、什么时候并行队列?
    //    挖个坑?后面我们在讨论?
        //课后记得复习
        //注意:这个队列执行一个操作->方法->闭包->执行闭包(核心:还是方法)->代码块
        //同步代码块->主线程执行的
        //方法泛型
        //代码块动态
        //串行队列定义:DispatchQueue(label: "database")
        //并行队列定义(加了一个attributes):DispatchQueue(label: "database", attributes: [])
        //百度搜索查看并行队列参数
        fileprivate var queue = DispatchQueue(label: "database", attributes: [])
        //根据key获取值
        fileprivate var queueKey = DispatchSpecificKey<Int>()
        //当前Connection指针->将Connection类对象引用->转为Int类型指针(引用)->强制类型转换
        //根据这个指针判定当前是串行队列,还是并行队列
        fileprivate lazy var queueContext: Int = unsafeBitCast(self, to: Int.self)
        func sync<T>(_ block: () throws -> T) rethrows -> T {
            //定义队列
            if DispatchQueue.getSpecific(key: queueKey) == queueContext {
                //串行队列->直接执行->主队列->排队执行
                return try block()
            } else {
                //并行队列->子队列->指通过queue管理执行,同时执行
                return try queue.sync(execute: block)
            }
        }
        
        
        //第七步:执行SQL语句
        func execute(_ SQL: String) throws {
            //同步代码块
            //"_"表示返回变量名接受"_"默认->变量通配符->没有类型
            _ = try sync {
                try self.check(sqlite3_exec(self._handle, SQL, nil, nil, nil))
            }
        }
        
        
    //    第八步:定义数据库基本操作属性
    //    1、关闭数据库
        deinit {
            //析构函数
            sqlite3_close(_handle)
        }
    //    2、数据库状态->是否是可读性数据库
        public var readonly: Bool {
            return sqlite3_db_readonly(_handle, nil) == 1
        }
    //    3、最后插入的一条数据所返回的行id->rowid
        public var lastInsertRowId: Int64 {
            return sqlite3_last_insert_rowid(_handle)
        }
    //    4、数据库受影响行数->changes
        public var changes: Int {
            return Int(sqlite3_changes(_handle))
        }
    //    5、数据库自从打开到目前为止数据库受影响行数
    //    insert、delete、update总共操作几次
    //    insert->10次(插入10条数据)
    //    delete->删除5条->干坏事5次
    //    update->更新2次->干坏事2次
    //    总共:到目前为止17次
        public var totalChanges: Int {
            return Int(sqlite3_total_changes(_handle))
        }
    //    6、中断任何长时间运行的查询操作(客户端少见)
    //    服务器开发->我开发服务器->100万数量级->耗费时间长
        public func interrupt(){
            sqlite3_interrupt(_handle)
        }
    //    7、数据库超时
        public var busyTimeout: Double = 0 {
            didSet{
                sqlite3_busy_timeout(_handle, Int32(busyTimeout * 1_000))
            }
        }
        
    }
    
    
    extension Connection.Location : CustomStringConvertible {
        
        //数据库位置
        public var description: String {
            switch self {
            case .inMemory:
                return ":memory"
            case .temporary:
                return ""
            case .uri(let URI):
                return URI
            }
        }
        
    }
    
    
    //定义Result枚举类
    //普及:枚举泛型
    public enum Result : Error {
        
        //SQLITE_OK->执行成功
        //SQLITE_ROW->执行下一行(成功)
        //SQLITE_DONE->执行完成
        fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
        
        case error(message: String, code: Int32)
        
        //errorCode->数据库返回结果
        init?(errorCode: Int32, connection: Connection){
            guard !Result.successCodes.contains(errorCode) else {
                return nil
            }
            //获取错误信息(封装数据库错误信息)
            let message = String(cString: sqlite3_errmsg(connection._handle))
            //初始化error信息
            self = .error(message: message, code: errorCode)
        }
        
    }
    

    调用

      let path = Bundle.main.path(forResource: "test", ofType: ".db")
            print(path!)
            let db = try! Connection(path!)
            try! db.execute("create table t_teacher(name text, email text)")
    

    相关文章

      网友评论

        本文标题:数据库连接-静态构建表

        本文链接:https://www.haomeiwen.com/subject/yjflbqtx.html