cocos2d-x sqlite 封装类

网上的封装类说心里话,用的很不舒服。

不知道其他的C++程序员用的数据库封装都是什么样子,至少对我这种PHP过来的程序员来说,这种还需要完全自己写sql的数据库封装类用起来很痛苦。


所以,为了以后不痛苦,只能现在痛苦一下了。把网上的类重新改了下

DBUtil.h

//
//  DBUtil.h
//
//  Created by Ron on 15/8/25.
//
//

#ifndef __DBUtil__
#define __DBUtil__

#include "sqlite3.h"
#include "cocos2d.h"

USING_NS_CC;

class DBUtil {
    
private:
    
    //数据库
    sqlite3* m_pDataBase;
    
private:
    
#pragma mark <构造 && 析构>
    
    DBUtil();
    
    virtual ~DBUtil();
    
public :
    
#pragma mark <创建 && 销毁单例>
    
    static DBUtil* getInstance();
    
    static void destoryInstance();
    
#pragma mark <自定义数据库操作>
    void resetParam();//重置操作数据
    
    /**
     *  创建表
     *
     *  @param where where条件字符串
     */
    void createTable(std::vector<std::string> param, std::string primaryName);
    
    /**
     *  table表名
     *
     *  @param where where条件字符串
     */
    DBUtil* table(std::string tableName);
    
    /**
     *  where条件
     *
     *  @param where where条件字符串
     */
    DBUtil* where(std::string where);
    
    /**
     *  插入数据
     *
     *  @param param 要插入的数据
     */
    int insert(std::map<std::string, std::string> param);
    
    /**
     *  查询,返回多个条件
     */
    std::vector<std::map<std::string, std::string>> select();
    
    /**
     *  查询,返回一个条件
     */
    std::map<std::string, std::string> find();
    
    /**
     *  查询,返回个数
     */
    int count();
    
    /**
     *  更新数据
     *
     *  @param param 要插入的数据
     */
    int update(std::map<std::string, std::string> param);
    
    /**
     *  删除
     */
    int del();
    
private:
    std::string ron_tableName;
    std::string ron_where;
    
    
public:
#pragma mark <数据库操作>
    
    /**
     *  打开数据库(创建)
     *
     *  @param aDataBaseName 数据库名
     */
    void openDBWithName();
    
    /**
     *  关闭数据库
     */
    void closeDB();
    
    /**
     *  创建数据表
     *
     *  @param aSql       建表sql语句
     *  @param aTableName 表名
     */
    void createTable(std::string aSql, std::string aTableName);
    
    /**
     *  通过表名查询该表是否存在
     *
     *  @param aTabelName 表秒
     *
     *  @return true: 存在 false: 不存在
     */
    bool isExistTableByName(std::string aTabelName);
    
    /**
     *  删除数据表
     *
     *  @param aSql       删表sql语句
     *  @param aTableName 表名
     */
    void deleteTable(std::string aSql, std::string aTableName);
    
    /**
     *  开始事务
     *
     *  @return 操作结果(sqlite3提供的宏)
     */
    int beginTransaction();
    
    /**
     *  提交事务(失败回滚)
     *
     *  @param aResult       操作结果
     *
     *  @return 操作结果(sqlite3提供的宏)
     */
    int comitTransaction(int aResult);
    
};

#endif /* defined(__DBUtil__) */

DBUtil.cpp

//
//  DBUtil.cpp
//
//  Created by ron on 15/8/25.
//
//

#include "DBUtil.h"

static DBUtil* s_pInstance = NULL;

const std::string cDBName = "gamedb";

#pragma mark <构造 && 析构>

DBUtil::DBUtil():m_pDataBase(NULL),ron_where(""),ron_tableName("")
{
    
}

DBUtil::~DBUtil() {
    
}

#pragma mark <创建 && 销毁单例>

DBUtil* DBUtil::getInstance() {
    if (!s_pInstance) {
        s_pInstance = new DBUtil();
    }
    return s_pInstance;
}

void DBUtil::destoryInstance() {
    delete s_pInstance;
    s_pInstance = NULL;
}

#pragma mark <数据库操作>

/**
 *  打开数据库(创建)
 *
 *  @param aDataBaseName 数据库名
 */
void DBUtil::openDBWithName() {
    std::string writeablePath = FileUtils::getInstance()->getWritablePath();
    CCLOG("path=%s", writeablePath.c_str());
    std::string dbPath = writeablePath + cDBName;
    
    int result = sqlite3_open(dbPath.c_str(), &m_pDataBase);
    char* errMsg = NULL;
    if (result != SQLITE_OK) {
        log("打开数据库失败,错误码:%d,错误原因:%s\n", result, errMsg);
    }
    
    if (errMsg) {
        sqlite3_free(errMsg);
        errMsg = NULL;
    }
}

/**
 *  关闭数据库
 */
void DBUtil::closeDB() {
    if (m_pDataBase) {
        sqlite3_close(m_pDataBase);
        m_pDataBase = NULL;
    }
}

/**
 *  创建数据表
 *
 *  @param aSql       建表sql语句
 *  @param aTableName 表名
 *
 *  @usage string sql = "create table user(id integer, username text, password text)";
 */
void DBUtil::createTable(std::string aSql, std::string aTableName) {
    
    openDBWithName();
    
    if (!isExistTableByName(aTableName)) {
        char* errMsg = NULL;
        int result = sqlite3_exec(m_pDataBase, aSql.c_str(), NULL, NULL, &errMsg);
        if (result != SQLITE_OK) {
            log("创建表失败,错误码:%d,错误原因:%s\n", result, errMsg);
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
        }
    }
    
    closeDB();
}

/**
 *  是否存在某张数据表的查询回调
 *
 *  @return 0
 */
int isExistTableCallback(void* para, int n_column, char ** column_value, char ** column_name) {
    bool *isExisted_= (bool*)para;
    *isExisted_= (**column_value) != '0';
    return 0;
}

/**
 *  通过表名查询该表是否存在
 *
 *  @param aTabelName 表秒
 *
 *  @return true: 存在 false: 不存在
 */
bool DBUtil::isExistTableByName(std::string aTabelName) {
    
    if (m_pDataBase) {
        //判断表是否存在
        bool isExist;
        char* errMsg = NULL;
        std::string sql = "select count(type) from sqlite_master where type = 'table' and name = '" + aTabelName + "'";
        int result = sqlite3_exec(m_pDataBase, sql.c_str(), isExistTableCallback, &isExist, &errMsg);
        
        if (result != SQLITE_OK) {
            log("查询表是否存在失败,错误码:%d,错误原因:%s\n", result, errMsg);
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
        }
        
        return isExist;
    }
    
    return false;
}

/**
 *  删除数据表
 *
 *  @param aSql       删表sql语句
 *  @param aTableName 表名
 *
 *  @usage string sql = "drop table name";
 */
void DBUtil::deleteTable(std::string aSql, std::string aTableName) {
    
    openDBWithName();
    
    beginTransaction();
    
    int result = 0;
    if (isExistTableByName(aTableName)) {
        char* errMsg = NULL;
        result = sqlite3_exec(m_pDataBase, aSql.c_str(), NULL, NULL, &errMsg);
        if (result != SQLITE_OK) {
            log("创建表失败,错误码:%d,错误原因:%s\n", result, errMsg);
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
        }
    }
    
    comitTransaction(result);
    
    closeDB();
    
}

/**
 *  开始事务
 *
 *  @return 操作结果(sqlite3提供的宏)
 */
int DBUtil::beginTransaction() {
    char* errMsg = NULL;
    int result = sqlite3_exec(m_pDataBase, "begin transaction", 0, 0, &errMsg);
    if (result != SQLITE_OK ){
        log("开始事务记录失败,错误码:%d,错误原因:%s\n", result, errMsg);
    }
    return result;
}

/**
 *  提交事务(失败回滚)
 *
 *  @param aResult       操作结果
 *
 *  @return 操作结果(sqlite3提供的宏)
 */
int DBUtil::comitTransaction(int aResult) {
    if (aResult == SQLITE_OK) {
        char* errMsg = NULL;
        int result = sqlite3_exec(m_pDataBase, "commit transaction", 0, 0, &errMsg);
        if (result != SQLITE_OK) {
            log("提交事务记录失败,错误码:%d,错误原因:%s\n" , result, errMsg);
        }
        return result;
    } else {
        char* errMsg = NULL;
        int result = sqlite3_exec(m_pDataBase, "rollback transaction", 0, 0, &errMsg);
        if (result != SQLITE_OK ) {
            log("回滚事务记录失败,错误码:%d,错误原因:%s\n", result, errMsg);
        }
        return result;
    }
}

#pragma mark 自定义数据库操作
DBUtil* DBUtil::table(std::string tableName)
{
    ron_tableName = tableName;
    
    return DBUtil::getInstance();
}

DBUtil* DBUtil::where(std::string where)
{
    std::string str = " WHERE ";
    ron_where =  str.append(where);
    
    return DBUtil::getInstance();
}

/**
 *  重置操作数据
 */
void DBUtil::resetParam()
{
    ron_tableName = "";
    ron_where = "";
}

/**
 *  查询回调
 *
 *  @return 0
 */
int selectCallback(void* para, int n_column, char** column_value, char** column_name ) {
    std::map<std::string, std::string> mapResults ;
    for (int i = 0; i < n_column; i++) {
        mapResults.insert(std::make_pair<std::string, std::string>((std::string)column_name[i], (std::string)column_value[i]));
    }
    std::vector<std::map<std::string, std::string> >* vect = (std::vector<std::map<std::string, std::string> >*)para;
    vect->push_back(mapResults);
    return 0;
}

std::vector<std::map<std::string, std::string>> DBUtil::select()
{
    //vector是查询的结果集,每一个结果都存在map中
    //map的第一string是key(字段名),第二个string是value(查询出的对应数据)
    std::vector<std::map<std::string, std::string> > vec;
    
    try {
        if (ron_tableName.empty()) {
            throw 0;//表名为空的话,则抛出异常
        }
        openDBWithName();
        
        std::string sql = "SELECT * FROM ";
        
        sql.append(ron_tableName);
        sql.append(ron_where);
        
        char* errMsg = NULL;
        int result = sqlite3_exec(m_pDataBase, sql.c_str(), selectCallback, &vec, &errMsg);
        if (result != SQLITE_OK) {
            log("查询失败,错误码:%d,错误原因:%s\n", result, errMsg);
            throw 0;
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
            throw 0;
        }
        
        resetParam();
        closeDB();
    } catch (...) {
        std::vector<std::map<std::string, std::string>> empty;
        resetParam();
        closeDB();
        
        return empty;
    }

    return vec;
}

/**
 *  查询回调
 *
 *  @return 0
 */
int findCallback(void* para, int n_column, char** column_value, char** column_name ) {
    std::map<std::string, std::string> mapResults ;
    
    mapResults.insert(std::make_pair<std::string, std::string>((std::string)column_name[0], (std::string)column_value[0]));
    for (int i = 0; i < n_column; i++) {
        mapResults.insert(std::make_pair<std::string, std::string>((std::string)column_name[i], (std::string)column_value[i]));
    }
    std::map<std::string, std::string>* map = (std::map<std::string, std::string>*)para;
    *map = mapResults;

    return 0;
}

std::map<std::string, std::string> DBUtil::find()
{
    //map的第一string是key(字段名),第二个string是value(查询出的对应数据)
    std::map<std::string, std::string> map;
    
    try {
        if (ron_tableName.empty()) {
            throw 0;//表名为空的话,则抛出异常
        }
        openDBWithName();
        
        std::string sql = "SELECT * FROM ";
        
        sql.append(ron_tableName);
        sql.append(ron_where);
        sql.append(" LIMIT 1");
        
        char* errMsg = NULL;
        int result = sqlite3_exec(m_pDataBase, sql.c_str(), findCallback, &map, &errMsg);
        if (result != SQLITE_OK) {
            log("查询失败,错误码:%d,错误原因:%s\n", result, errMsg);
            throw 0;
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
            throw 0;
        }
        
        resetParam();
        closeDB();
    } catch (...) {
        resetParam();
        closeDB();
        std::map<std::string, std::string> empty;
        
        return empty;
    }
    
    return map;
}

/**
 *  查询数据条数回调
 *
 *  @return 0
 */
int countCallback(void* para, int n_column, char** column_value, char** column_name) {
    int* count = (int*)para;
    *count = (int)atof(column_value[0]);
    return 0;
}

/**
 *  查询记录的条数
 *
 *  @param sql 查询记录sql语句
 *
 *  @return 记录条数
 */
int DBUtil::count() {
    int count = 0;
    try {
        if (ron_tableName.empty()) {
            throw 0;//表名为空的话,则抛出异常
        }
        openDBWithName();
        
        std::string sql = "SELECT * FROM ";
        
        sql.append(ron_tableName);
        sql.append(ron_where);
        
        char* errMsg = NULL;
        int result = sqlite3_exec(m_pDataBase, sql.c_str(), countCallback, &count, &errMsg);
        if (result != SQLITE_OK) {
            log("查询失败,错误码:%d,错误原因:%s\n", result, errMsg);
            throw 0;
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
            throw 0;
        }
        
        resetParam();
        closeDB();
    } catch (...) {
        resetParam();
        closeDB();
        
        return 0;
    }
    
    return count;
}

void DBUtil::createTable(std::vector<std::string> param, std::string primaryName)
{
    try {
        if (ron_tableName.empty()) {
            throw 0;//表名为空的话,则抛出异常
        }
        openDBWithName();
        
        std::string sql = "CREATE TABLE ";
        
        sql.append(ron_tableName);
        sql.append("(");
        
        for (auto value : param) {
            sql.append(value);
            if (value == primaryName) {
                sql.append(" INTEGER PRIMARY KEY AUTOINCREMENT");
            }
            sql.append(",");
        }
        
        sql.erase(sql.end()-1);
        sql.append(")");
        
        if (!isExistTableByName(ron_tableName)) {
            char* errMsg = NULL;
            int result = sqlite3_exec(m_pDataBase, sql.c_str(), NULL, NULL, &errMsg);
            if (result != SQLITE_OK) {
                log("创建表失败,错误码:%d,错误原因:%s\n", result, errMsg);
            }
            
            if (errMsg) {
                sqlite3_free(errMsg);
                errMsg = NULL;
            }
        }
    } catch (...) {
        
    }
    
    resetParam();
    closeDB();
}

int DBUtil::insert(std::map<std::string, std::string> param)
{
    int result = 0;
    try {
        if (ron_tableName.empty()) {
            throw 0;//表名为空的话,则抛出异常
        }
        
        openDBWithName();
        
        beginTransaction();
        
        std::string sql = "INSERT INTO ";
        sql.append(ron_tableName);
        sql.append(" (");
        
        for (std::map<std::string, std::string>::iterator i = param.begin(); i != param.end(); i++) {
            sql.append(i->first);
            sql.append(",");
        }
        sql.erase(sql.end()-1);
        sql.append(") VALUES (");
        
        for (std::map<std::string, std::string>::iterator i = param.begin(); i != param.end(); i++) {
            sql.append("\"");
            sql.append(i->second);
            sql.append("\",");
        }
        sql.erase(sql.end()-1);
        sql.append(");");
        
        char* errMsg = NULL;
        result = sqlite3_exec(m_pDataBase, sql.c_str(), NULL, NULL, &errMsg);
        if (result != SQLITE_OK) {
            log("插入记录失败,错误码:%d,错误原因:%s\n", result, errMsg );
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
        }
        
        comitTransaction(result);
        
    } catch (...) {
        result = 1;
    }
    
    resetParam();
    closeDB();
    
    return result;
}

int DBUtil::update(std::map<std::string, std::string> param)
{
    int result = 0;
    try {
        if (ron_tableName.empty() || ron_where.empty()) {
            throw 0;//表名为空或者where条件为空的话,则抛出异常
        }
        
        openDBWithName();
        
        beginTransaction();
        
        std::string sql = "UPDATE ";
        sql.append(ron_tableName);
        sql.append(" SET ");
        
        for (std::map<std::string, std::string>::iterator i = param.begin(); i != param.end(); i++) {
            sql.append(i->first);
            sql.append("=\"");
            sql.append(i->second);
            sql.append("\",");
        }
        sql.erase(sql.end()-1);
        
        sql.append(ron_where);
        
        char* errMsg = NULL;
        result = sqlite3_exec(m_pDataBase, sql.c_str(), NULL, NULL, &errMsg);
        if (result != SQLITE_OK) {
            log("更新记录失败,错误码:%d,错误原因:%s\n", result, errMsg );
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
        }
        
        comitTransaction(result);
    } catch (...) {
        result = 1;
    }
    
    resetParam();
    closeDB();
    
    return result;
}

int DBUtil::del()
{
    int result = 0;
    try {
        if (ron_tableName.empty() || ron_where.empty()) {
            throw 0;//表名为空或者where条件为空的话,则抛出异常
        }
        
        openDBWithName();
        
        beginTransaction();
        
        std::string sql = "DELETE FROM ";
        sql.append(ron_tableName);
        sql.append(ron_where);
        
        char* errMsg = NULL;
        result = sqlite3_exec(m_pDataBase, sql.c_str(), NULL, NULL, &errMsg);
        if (result != SQLITE_OK) {
            log("删除记录失败,错误码:%d,错误原因:%s\n", result, errMsg );
        }
        
        if (errMsg) {
            sqlite3_free(errMsg);
            errMsg = NULL;
        }
        
        comitTransaction(result);
    } catch (...) {
        result = 1;
    }
    
    resetParam();
    closeDB();
    
    return result;
}



用法也很简单

std::vector<std::string> param;
        param.push_back("id");
        param.push_back("name");
        param.push_back("age");
        
        DBUtil::getInstance()->table("rontab2")->createTable(param, "id");//建表
        
        std::map<std::string, std::string> m;
        m["name"] = "wahaha";
        m["age"] = "年龄";
        
        DBUtil::getInstance()->table("rontab3")->insert(m);//添加
        
        auto data = DBUtil::getInstance()->table("rontab3")->select();//查找
        
        DBUtil::getInstance()->where("id = 8")->table("rontab3")->update(m);//更新
        
        DBUtil::getInstance()->where("id=3")->table("rontab3")->del();//删除

这种增删改查是不是简单到没朋友?


不过实话实说。缺陷还是不少。

首先,建表只能建无类型的,虽然sqlite会自动转换,但是由于我的insert和update的缺陷,导致,除了主键,其他都是字符串类型。


还有,代码里的string字符串连接确实有点坑爹了。真心对C++不太熟悉,图省事,就先这样了。


确实有很多可以优化的地方,但是,封装这样一个类真心对我来说太枯燥。我宁肯写10000行代码去开发游戏的逻辑,也不想写100行这种代码。所以,先这样吧,以后哪天心情好了,再重新优化一下吧。或者哪位兄弟无聊也可以为人类做下贡献:)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值