使用SQLite模拟对象数据库

        日常开发中,需要保存一些软件运行用到的一些数据,比如软件设置或者软件读入的数据,这些数据我以前一般都是会写成一个类或者结构体去保存,简单的我会按一定的分隔符组合成字符串,然后需要保存的时候一行一个,保存成txt,在需要读取的时候一次性读入,再按分隔符分割.这样做的好处是可以代码写得很快,保存跟恢复十几行代码就搞定了,但是后期维护起来超级麻烦,配置文件一大堆,而且效率也不是很高,每次都得是整体读入写出,即时性保存不是很方便.而且这种代码看起来很”蠢”,比如下面这个:

使用SQLite模拟对象数据库_第1张图片

         真的很怕 address 里面突然包含个 # ……

         复杂的话,我会使用数据库,比如最钟爱的SQLite,但是使用数据库就没那么快速了,首先要先设计表,然后要想办法保证这个数据库存在(如果数据库不存在,要使用sql语句创建对应的表,这个也比较麻烦),然后数据的增删改查都需要在持有数据库的连接的情况下去写对应的sql语句了,代码量比较大.不过好在这些都写完以后后期维护就简单多了,效率也不错,可以随时使用sql语句查询需要的数据.

         大多数时间不急的情况下,我都会选择是SQLite,天生对一堆文本配置文件很反感,在多次的SQLite的使用中,我也逐渐摸索除了一些可以减少代码书写量的一些办法,最近正好有需求要用到SQLite数据库,索性就总结了一下经验,写出了一个SQLite版的”对象数据库”,在使用上我本来想尽量往ObjectBox(一个目前在Android上推出的基于对象的数据库,速度超快,我的实测数据比SQLite快了五倍的样子,有兴趣的可以去试试)靠拢,但是好多用法都想不到办法去实现,索性就另辟蹊径了,目前现在来看,我的用法也不比ObjectBox复杂,某些方面甚至可以说更简单一点.所谓基于对象的数据库,我的理解就是数据操作是基于对象的,而不是去操作某个Table里面的某行,不过我这里是用sqlite数据库去模拟,所以我是一张表就对应了一个类.反之,一个类我就用一张表去保存.为了简化操作,我在notepad++上写了一个插件,差不多是一键完成数据库到类的生成工作.

         框架使用步骤(以Qt为例,Java类似)

        比如我有这么一个表:

         使用SQLite模拟对象数据库_第2张图片

         (1).由数据库生成对应的的类.

         有了数据库以后可以使用我在notepad++上写的一个插件一步完成类的生成和注册代码,自动生成的代码如下:

         头文件:

#ifndef __7ef8d26d_d64a_4257_bae5_93d8dd24dadc_H__
#define __7ef8d26d_d64a_4257_bae5_93d8dd24dadc_H__
#include 
#include "qtsqlitetool.h"

class Person :public SqlTableBase 
{
public:
	Person();
	Person(QSqlQuery query);

	virtual QString tableName() const override;
	virtual QString sqlWhere() const override;
	virtual QStringList itemNames() const override;
	virtual QString createStr() const override;
	virtual void updateWhere() override;
	virtual QString dbGuid() const override;
	virtual bool insertIntoDb() override;
	virtual bool updateToDb() override;
	virtual bool removeFromDb() override;
	virtual QVariantMap contentValues() const override;

	QString toString() const ;
	bool init(QString str);

	QString getName() const;
	void setName(QString val);

	int getAge() const;
	void setAge(int val);

	QString getIDCard() const;
	void setIDCard(QString val);

private:
	QString m_sqlwhere;
	QString m_Name;
	int m_Age;
	QString m_IDCard;
};
#endif // __7ef8d26d_d64a_4257_bae5_93d8dd24dadc_H__

        CPP文件:

#include "person.h"
#include 
#include 

Person::Person()
{

}

Person::Person(QSqlQuery query)
{
	m_Name = query.value("Name").toString();
	m_Age = query.value("Age").toInt();
	m_IDCard = query.value("IDCard").toString();
	updateWhere();
}

QString Person::tableName() const
{
	return "Person";
}

QString Person::sqlWhere() const
{
	return m_sqlwhere;
}

QStringList Person::itemNames() const
{
	return QStringList() << "Name"<< "Age"<< "IDCard"; 
}

QString Person::createStr() const 
{
	return "CREATE TABLE Person( Name VARCHAR, Age INTEGER, IDCard VARCHAR)";
}

void Person::updateWhere() 
{
	m_sqlwhere = QString(" Name = '%1' ").arg(m_Name);
}

QVariantMap Person::contentValues() const
{
	QVariantMap val;
	val.insert("Name", m_Name);
	val.insert("Age", m_Age);
	val.insert("IDCard", m_IDCard);
	return val;
}

QString Person::dbGuid() const
{
	return "051e1ae7_aba9_48d9_ba6f_17ce5afe9730";
}

bool Person::insertIntoDb()
{
	SqlItemInsert
 }

bool Person::updateToDb()
{
	SqlItemUpdate
 }

bool Person::removeFromDb()
{
	SqlItemRemove
 }

QString Person::toString() const 
{
	QVariantMap varmap = contentValues();
	QJsonDocument doc = QJsonDocument::fromVariant(QVariant(varmap));
	QByteArray jba = doc.toJson();
	QString jsonString = QString(jba);
	return jsonString;
}

bool Person::init(QString str)
{
	QByteArray njba = str.toUtf8();
	QJsonObject nobj = QJsonObject(QJsonDocument::fromJson(njba).object());
	QVariantMap query = nobj.toVariantMap();
	m_Name = query.value("Name").toString();
	m_Age = query.value("Age").toInt();
	m_IDCard = query.value("IDCard").toString();
	updateWhere();
	return true;
}

QString Person::getName()  const
{
	return m_Name;
}

void Person::setName(QString val)
{
	m_Name = val;
}

int Person::getAge()  const
{
	return m_Age;
}

void Person::setAge(int val)
{
	m_Age = val;
}

QString Person::getIDCard()  const
{
	return m_IDCard;
}

void Person::setIDCard(QString val)
{
	m_IDCard = val;
}

         注册cpp:

#include "qtsqlitetool.h"  
#include "person.h"

BeginDbRegister
RegisterDB(Person)
EndDbRegister

         其中用到的依赖可以在notepad++导出,只有一个cpp及头文件


         (2).初始化并打开数据库:

 QtSqliteToolManager::instance()->openDb(dbPath,Person().dbGuid());

         参数第二项可以是该数据库任意类取出的guid即可.


         (3)数据插入

Personp;
…//p的赋值操作
boolisok = p.insertIntoDb();//isok代表是否插入数据库成功(如类没有正确注册或者数据库没打开就会失败)

         (4)数据删除

         boolisok = p. removeFromDb ();


         (5)数据更新

         boolisok = p.updateToDb();


         (6)查询数据

        

 QListpers = QueryToList();//查询出所有的Person并填充到list里面
 //这个函数还可以接where和order两个参数,实现筛选和排序(默认为空)  如:
 QList pers =QueryToList("Age> 18","Name");//查询出符合年龄大于18且按name字段排好序的列表      

         类似的接口还有QueryToVector和QueryToMap…等,可以一行搞定查询


        总结:目前实现了数据库到类的一键生成,增删改不再需要书写sql语句及关心数据库连接,调用对象一个无参方法就可以完成操作,查询数据也只需调用一个函数,已经大大减少代码的书写量了,另外整个框架还提供了一些的其他功能,比如使用json生成及还原对象,工具类的事务开启及默认属性表等,可以去查看接口.下面的改进目前是计划是做参考安卓的数据更新方式,在更改了数据库结构的情况下做到无缝过渡.

       相关的notepad++的插件,在http://download.csdn.net/download/lixiangmaty/10148758 可以下载到.

       

         附上工具类的完整代码:

          

#ifndef QTSQLITETOOL_H
#define QTSQLITETOOL_H
//Create By lixiangmaty
//CSDN http://blog.csdn.net/lixiangmaty

#include 
#include 
#include 
#include 
#include 
#include 
#include 

class QtSqliteTool;
class QSqlRecord;
class SqlTableBase;
struct DbInfo
{QStringList tableNames;QStringList tableCreateStrs;
void append(QString name, QString create){
	tableNames.append(name); tableCreateStrs.append(create);}};

#define SqlItemInsert QtSqliteTool* tool = QtSqliteToolManager::instance()->getTool(dbGuid());\
if (tool == NULL)\
	return false;\
return tool->insert(*this);

#define SqlItemUpdate QtSqliteTool* tool = QtSqliteToolManager::instance()->getTool(dbGuid());\
if (tool == NULL) \
	return false; \
return tool->update(*this);

#define SqlItemRemove QtSqliteTool* tool = QtSqliteToolManager::instance()->getTool(dbGuid()); \
if (tool == NULL) \
return false; \
return tool->remove(*this);

#define BeginDbRegister class DBRegisterTool \
		{ \
public: \
	DBRegisterTool()\
			{ 

#define EndDbRegister 	} \
		}; \
static DBRegisterTool registerdb; 

#define RegisterDB(Table)  { Table t;DBRegisterAppend(t);}

template
QList QueryToList(QtSqliteTool* tool,QString wherestr = QString(),QString orderby = QString())
{
	QList res;
	T table;
	QSqlQuery query = tool->query(table, wherestr,orderby);
	if (query.first())
	{
		do
		{
			T item(query);
			res.append(item);
		} while (query.next());
	}
	return res;
};

template
QList QueryToList(QString wherestr = QString(), QString orderby = QString())
{
	QtSqliteTool* tool = QtSqliteToolManager::instance()->getTool(T().dbGuid());
	if (tool==NULL)
		return QList();
	return QueryToList(tool, wherestr, orderby);
};

template
QVector QueryToVector(QtSqliteTool* tool, QString wherestr = QString(), QString orderby = QString())
{
	QVector res;
	T table;
	QSqlQuery query = tool->query(table, wherestr, orderby);
	if (query.first())
	{
		do
		{
			T item(query);
			res.append(item);
		} while (query.next());
	}
	return res;
};

template
QVector QueryToVector(QString wherestr = QString(), QString orderby = QString())
{
	QtSqliteTool* tool = QtSqliteToolManager::instance()->getTool(T().dbGuid());
	if (tool == NULL)
		return QVector();
	return QueryToVector(tool, wherestr, orderby)
};

template 
QMap QueryToMapInt(QtSqliteTool* tool, QString key, QString wherestr = QString())
{
	QMap res;
	T table;
	QSqlQuery query = tool->query(table, wherestr);
	if (query.first())
	{
		do
		{
			T item(query);
			int itemkey = query.value(key).toInt();
			res.insert(itemkey, item);
		} while (query.next());
	}
	return res;
};

template 
QMap QueryToMapInt(QString key, QString wherestr = QString())
{
	QMap res;
	T table;
	QtSqliteTool* tool = QtSqliteToolManager::instance()->getTool(table.dbGuid());
	if (tool == NULL)
		return res;
	return QueryToMapInt(tool, key, wherestr);
};

template 
QMap QueryToMapQString(QtSqliteTool* tool, QString key, QString wherestr = QString())
{
	QMap res;
	T table;
	QSqlQuery query = tool->query(table, wherestr);
	if (query.first())
	{
		do
		{
			T item(query);
			QString itemkey = query.value(key).toString();
			res.insert(itemkey, item);
		} while (query.next());
	}
	return res;
};

template 
QMap QueryToMapQString(QString key, QString wherestr = QString())
{
	QtSqliteTool* tool = QtSqliteToolManager::instance()->getTool(T().dbGuid());
	if (tool == NULL)
		QMap res;
	return QueryToMapQString(tool, key, wherestr);
};

void DBRegisterAppend(const SqlTableBase& base);

class SqlTableBase
{
public:
	//************************************
	// name: tableName
	// 返回表名称
	// return: QString
	//************************************
	virtual QString tableName() const = 0;
	//************************************
	// name: sqlWhere
	// 返回用于更新当前项的时候where语句(不包含where)
	// return: QString
	//************************************
	virtual QString sqlWhere() const = 0;
	//************************************
	// name: itemNames
	// 返回表各字段名称
	// return: QStringList
	//************************************
	virtual QStringList itemNames() const = 0;
	//************************************
	// name: createStr
	// 返回该表的创建sql语句
	// return: QString
	//************************************
	virtual QString createStr() const = 0;
	//************************************
	// name: contentValues
	// 返回该项每个字段对应的值
	// return: QVariantMap
	//************************************
	virtual QVariantMap contentValues() const = 0;
	//************************************
	// name: updateWhere
	// 更新项的where语句(理应在构建或者插入/更新后的时候调用[插入/更新后会自动调用],
	// 因为里面的值一旦改了就无法知道数据库的值了)
	// return: void
	//************************************
	virtual void updateWhere() = 0;

	//************************************
	// name: dbGuid
	// 返回数据库的guid(用于确定属于哪个数据库)
	// return: QString
	//************************************
	virtual QString dbGuid() const = 0;

	//************************************
	// name: insertIntoDb
	// 插入数据库
	// return: bool 是否插入成功
	//************************************
	virtual bool insertIntoDb() = 0;

	//************************************
	// name: updateToDb
	// 更新到数据库中
	// return: bool 是否更新成功
	//************************************
	virtual bool updateToDb() = 0;

	//************************************
	// name: removeFromDb
	// 从数据库中移除
	// return: bool 是否移除成功
	//************************************
	virtual bool removeFromDb() = 0;

};

class QtSqliteToolManager
{
public:
	//************************************
	// name: instance
	// 获取全局单例
	// return: QtSqliteToolManager*
	//************************************
	static QtSqliteToolManager* instance();
	//************************************
	// name: openDb
	// 打开新数据库
	// return: QtSqliteTool*
	// Parameter: const QString & dbpath
	// Parameter: const SqlTableBase & table
	//************************************
	QtSqliteTool* openDb(const QString& dbpath, const QString& guid);
	//************************************
	// name: closeDB
	// 关闭数据库
	// return: bool
	// Parameter: const QString & dbpath
	//************************************
	bool closeDB(const QString& dbpath);
	//************************************
	// name: getTool
	// 获取工具类
	// return: QtSqliteTool*
	// Parameter: const QString & guid
	//************************************
	QtSqliteTool* getTool(const QString& guid);
	~QtSqliteToolManager();
private:
	friend void DBRegisterAppend(const SqlTableBase& base);
private:
	QtSqliteToolManager();
	QMap m_dbs;
	QMap m_dbInfos;
};

class QtSqliteTool
{
public:
	QtSqliteTool();
	~QtSqliteTool();
	//************************************
	// name: QtSqliteTool
	// 工具类的构造函数
	// Parameter: QString path 数据库的路径
	// Parameter: QString propertyTable 存放property的表(无须存在,如不存在会自动创建,这里只需要个名字,不填也可以,默认PropertyTable)
	//************************************
	QtSqliteTool(QString path, QString propertyTable = "PropertyTable");
	//************************************
	// name: getDb
	// 获取数据库连接实例,供实现更多自定义操作
	// return: QSqlDatabase*
	//************************************
	QSqlDatabase* getDb();
	//************************************
	// name: getDbpath
	// 获取数据库的路径
	// return: QString
	//************************************
	QString getDbpath() const;
	//************************************
	// name: setDbpath
	// 设置数据库的路径
	// return: void
	// Parameter: QString val
	//************************************
	void setDbpath(QString val);
	//************************************
	// name: open
	// 开始链接数据库
	// return: bool
	//************************************
	bool open();
	//************************************
	// name: close
	// 关闭数据库连接
	// return: bool
	//************************************
	bool close();
	//************************************
	// name: tableExist
	// 根据表名判断某表是否存在
	// return: bool 是否存在
	// Parameter: const QString & tabName 表名
	//************************************
	bool tableExist(const QString &tabName);
	//************************************
	// name: tableNames
	// 返回数据库所有的表名
	// return: QT_NAMESPACE::QStringList
	//************************************
	QStringList tableNames();
	//************************************
	// name: record
	// 获取某表的结构
	// return: QSqlRecord 结构
	// Parameter: QString tabName 表名
	//************************************
	QSqlRecord record(QString tabName);
	//************************************
	// name: clearTable
	// 删除某表的所有数据
	// return: bool 是否清空成功
	// Parameter: const QString & table 表名
	//************************************
	bool clearTable(const QString & table);
	//************************************
	// name: creatTable
	// 创建表
	// return: bool 是否创建成功
	// Parameter: const QString & creatsql 创建表对应的sql语句
	//************************************
	bool creatTable(const QString & creatsql);
	//************************************
	// name: creatTable
	// 根据类来创建表
	// return: bool
	// Parameter: SqlTableBase & object
	//************************************
	bool creatTable(SqlTableBase& object);
	//************************************
	// name: deleteTable
	// 删除表
	// return: bool 是否删除成功
	// Parameter: const QString & table 表名
	//************************************
	bool deleteTable(const QString & table);
	//************************************
	// name: insert
	// 往数据库里面插入行
	// return: bool 是否插入成功
	// Parameter: SqlTableBase & object 行对应的类
	//************************************
	bool insert(SqlTableBase& object);
	//************************************
	// name: insert
	// 往数据库里面插入行
	// return: bool 是否插入成功
	// Parameter: const QString & tablename 表名
	// Parameter: QVariantMap & val 字段的键值对
	//************************************
	bool insert(const QString & tablename, QVariantMap& val);
	//************************************
	// name: update
	// 更新行
	// return: bool 是否更新成功
	// Parameter: SqlTableBase & object 行对应的类
	//************************************
	bool update(SqlTableBase& object);
	//************************************
	// name: update
	// 更新行
	// return: bool是否更新成功
	// Parameter: const QString & tablename 表名
	// Parameter: const QString & wheresql 更新的where语句
	// Parameter: QVariantMap & val  字段的键值对
	//************************************
	bool update(const QString & tablename, const QString &wheresql, QVariantMap& val);
	//************************************
	// name: remove
	// 删除行
	// return: bool 是否删除成功
	// Parameter: const SqlTableBase & object 行对应的类
	//************************************
	bool remove(const SqlTableBase& object);
	//************************************
	// name: remove
	// 删除行 
	// return: bool 是否删除成功
	// Parameter: const QString & tablename 表名
	// Parameter: const QString & wheresql where语句
	//************************************
	bool remove(const QString & tablename, const QString &wheresql);
	//************************************
	// name: query
	// 查询数据
	// return: QSqlQuery 查询后的结果
	// Parameter: const QString & tablename 表名
	// Parameter: const QStringList & itemname 要查询的字段集合(为空会读取所有) 
	// Parameter: const QString & sqlwhere where语句
	// Parameter: const QString & orderBy 排序依据
	//************************************
	QSqlQuery query(const QString & tablename, const QStringList& itemname = QStringList(), const QString & sqlwhere = "", const QString & orderBy = "");
	//************************************
	// name: query
	// 查询数据
	// return: QSqlQuery 查询后的结果
	// Parameter: const SqlTableBase & object 表对应的类
	// Parameter: const QString & sqlwhere where语句
	// Parameter: const QString & orderBy 排序依据
	//************************************
	QSqlQuery query(const SqlTableBase& object, const QString & sqlwhere = "", const QString & orderBy = "");
	//************************************
	// name: queryToList
	// 查询数据并填充到QList里面 
	// return: QList 结果
	// Parameter: const QString & tablename 表名
	// Parameter: QStringList itemname  要查询的字段集合(为空会读取所有) 
	// Parameter: const QString & sqlwhere where语句
	// Parameter: const QString & orderBy 排序依据
	//************************************
	QList queryToList(const QString & tablename, QStringList itemname = QStringList(), const QString & sqlwhere = "", const QString & orderBy = "");
	//************************************
	// name: isExist
	// 判断某行数据是否存在
	// return: bool 是否存在
	// Parameter: const QString & tableName 表名
	// Parameter: const QString & sqlwhere where语句
	//************************************
	bool isExist(const QString & tableName, const QString & sqlwhere);
	//************************************
	// name: transaction
	// 开启事务
	// return: bool
	//************************************
	bool transaction();
	//************************************
	// name: commit
	// 提交事务
	// return: bool
	//************************************
	bool commit();
	//************************************
	// name: rollback
	// 回滚事务
	// return: bool
	//************************************
	bool rollback();
	//************************************
	// name: getPropertyTable
	// 获取属性表的名称
	// return: QString
	//************************************
	QString getPropertyTable();
	//************************************
	// name: setPropertyTable
	// 设置属性表名称
	// return: bool
	// Parameter: QString tableName
	//************************************
	bool setPropertyTable(QString tableName);
	//************************************
	// name: property
	// 获取属性
	// return: QString 属性值
	// Parameter: QString key 属性key
	// Parameter: QString defaultVal 默认值
	//************************************
	QString property(QString key, QString defaultVal);
	//************************************
	// name: setProperty
	// 设置属性
	// return: bool 是否设置成功
	// Parameter: QString key 属性key
	// Parameter: QString val 属性值
	//************************************
	bool setProperty(QString key, QString val);
	//************************************
	// name: getLastErr
	// 获取最后的错误
	// return: QString
	//************************************
	QString getLastErr();
private:
	QSqlDatabase m_db;
	QString m_dbpath;
	QString m_lasterr;
	QString m_propertyTable;
	bool m_checkPropertyTable;
};

#endif // QTSQLITETOOL_H

cpp:

 

#include "qtsqlitetool.h"
#include "QSqlError"
#include "QSqlRecord"
#include "QSqlField"

#define CheckDb if (!m_db.isValid()||!m_db.isOpen()) \
	{ \
		return false; \
}

QtSqliteTool::QtSqliteTool() :m_propertyTable("PropertyTable"), m_checkPropertyTable(false)
{

}

QtSqliteTool::QtSqliteTool(QString path,QString propertyTable) 
{
	m_dbpath = path;
	m_propertyTable = propertyTable;
	
}

QtSqliteTool::~QtSqliteTool()
{
	if (m_db.isOpen())
	{
		m_db.close();
	}
}

QSqlDatabase* QtSqliteTool::getDb()
{
	return &m_db;
}

QString QtSqliteTool::getDbpath() const
{
	return m_dbpath;
}

void QtSqliteTool::setDbpath(QString val)
{
	m_dbpath = val;
}

bool QtSqliteTool::open()
{
	if (m_dbpath.isEmpty())
	{
		return false;
	}
	m_db = QSqlDatabase::database(m_dbpath);
	if (!m_db.isValid())
	{
		m_db = QSqlDatabase::addDatabase("QSQLITE", m_dbpath);
		m_db.setDatabaseName(m_dbpath);
	}
	if (m_db.isOpen())
	{
		return true;
	}
	bool res = m_db.open();
	return res;
}

bool QtSqliteTool::close()
{
	if (!m_db.isValid())
	{
		return false;
	}
	m_db.close();
	return true;
}

bool QtSqliteTool::tableExist(const QString &tabName)
{
	CheckDb
	QStringList tables = m_db.tables();
	return tables.contains(tabName);
}

QStringList QtSqliteTool::tableNames()
{
	return 	m_db.isValid() ? m_db.tables() : QStringList();
}

bool QtSqliteTool::clearTable(const QString & table)
{
	CheckDb
	QSqlQuery query(m_db);
	bool res = query.exec(QString("DELETE FROM %1").arg(table));
	if (!res)
	{
		m_lasterr = query.lastError().text();
	}
	return res;
}

QString QtSqliteTool::getLastErr()
{
	return m_lasterr;
}

bool QtSqliteTool::creatTable(const QString & creatsql)
{
	CheckDb
	QSqlQuery query(m_db);
	bool res = query.exec(creatsql);
	if (!res)
	{
		m_lasterr = query.lastError().text();
	}
	return res;
}

bool QtSqliteTool::creatTable(SqlTableBase& object)
{
	CheckDb
	if (tableExist(object.tableName()))
	{
		return true;
	}
	return creatTable(object.createStr());
}

bool QtSqliteTool::deleteTable(const QString & table)
{
	CheckDb
	QSqlQuery query(m_db);
	bool res = query.exec(QString("DROP TABLE %1").arg(table));
	if (!res)
	{
		m_lasterr = query.lastError().text();
	}
	return res;
}

bool QtSqliteTool::insert(SqlTableBase& object)
{
	CheckDb
	QVariantMap val = object.contentValues();
	bool res = insert(object.tableName(), val);
	if (res)
		object.updateWhere();
	return res;
}

bool QtSqliteTool::insert(const QString & tablename, QVariantMap& val)
{
	CheckDb
	if (val.size() == 0)
		return false;
	QString insertstr = QString(" INSERT INTO %1 (").arg(tablename);
	QString valstr = QString(" VALUES ( ");
	for (auto i = val.begin(); i != val.end(); ++i)
	{
		QString key = i.key();
		if (i != val.begin())
		{
			insertstr.append(",[" + key+"]");
			valstr.append(",:" + key);
		}
		else
		{
			insertstr.append("["+key+"]");
			valstr.append(":" + key);
		}
	}
	insertstr.append(" )");
	valstr.append(" )");
	insertstr.append(valstr);
	QSqlQuery query(m_db);
	query.prepare(insertstr);
	for (auto i = val.begin(); i != val.end(); ++i)
	{
		query.bindValue(":" + i.key(), i.value());
	}
	bool res = query.exec();
	if (!res)
	{
		m_lasterr = query.lastError().text();
	}
	return res;

}

bool QtSqliteTool::update(SqlTableBase& object)
{
	CheckDb
		
	QVariantMap val = object.contentValues();
	bool res = update(object.tableName(), object.sqlWhere(), val);
	if (res)
		object.updateWhere();
	return res;
}

bool QtSqliteTool::update(const QString & tablename, const QString &wherestr, QVariantMap& val)
{
	CheckDb
	if (val.size() == 0)
		return false;
	QString updatestr = QString("UPDATE %1 SET ").arg(tablename);
	for (auto i = val.begin(); i != val.end(); ++i)
	{
		QString key = i.key();
		if (i != val.begin())
		{
			updatestr.append(QString(" , [%1] = :%1").arg(key));
		}
		else
		{
			updatestr.append(QString("[%1] = :%1").arg(key));
		}
	}
	if (!wherestr.isEmpty())
	{
		updatestr.append(" WHERE " + wherestr);
	}

	QSqlQuery query(m_db);
	if (!query.prepare(updatestr))
	{
		m_lasterr = query.lastError().text();
		return false;
	}
	for (auto i = val.begin(); i != val.end(); ++i)
	{
		query.bindValue(":" + i.key(), i.value());
	}
	bool res = query.exec();
	if (!res)
	{
		m_lasterr = query.lastError().text();
	}
	return res;
}

bool QtSqliteTool::remove(const SqlTableBase& object)
{
	return remove(object.tableName(), object.sqlWhere());
}

bool QtSqliteTool::remove(const QString & tablename, const QString &wheresql)
{
	CheckDb
	QString wherestr = wheresql;
	if (wherestr.isEmpty())
	{
		return false;
	}
	QString updatestr = QString("DELETE FROM %1 WHERE %2 ").arg(tablename).arg(wherestr);
	QSqlQuery query(m_db);
	if (!query.exec(updatestr))
	{
		m_lasterr = query.lastError().text();
		return false;
	}
	return true;
}

QSqlQuery QtSqliteTool::query(const QString & tablename, const QStringList& itemname, const QString & sqlwhere /*= ""*/, const QString & orderBy /*= ""*/)
{
	if (!m_db.isValid() || !m_db.isOpen())
	{
		return QSqlQuery();
	}
	QString selectstr = QString("SELECT ");
	for (int i = 0; i < itemname.size(); i++)
	{
		selectstr.append(i == 0 ? itemname.at(i) : "," + itemname.at(i));
	}
	selectstr.append(QString(" FROM %1").arg(tablename));
	if (!sqlwhere.isEmpty())
	{
		selectstr.append(QString(" WHERE %1").arg(sqlwhere));
	}
	if (!orderBy.isEmpty())
	{
		selectstr.append(QString(" ORDER BY %1").arg(orderBy));
	}
	QSqlQuery query(m_db);
	query.exec(selectstr);
	return query;
}

QSqlQuery QtSqliteTool::query(const SqlTableBase& object, const QString & sqlwhere /*= ""*/, const QString & orderBy /*= ""*/)
{
	if (!m_db.isValid() || !m_db.isOpen())
	{
		return QSqlQuery();
	}
	QString selectstr = QString("SELECT ");
	QStringList itemname = object.itemNames();
	for (int i = 0; i < itemname.size(); i++)
	{
		selectstr.append(i == 0 ? itemname.at(i) : "," + itemname.at(i));
	}
	selectstr.append(QString(" FROM %1").arg(object.tableName()));
	if (!sqlwhere.isEmpty())
	{
		selectstr.append(QString(" WHERE %1").arg(sqlwhere));
	}
	if (!orderBy.isEmpty())
	{
		selectstr.append(QString(" ORDER BY %1").arg(orderBy));
	}
	QSqlQuery query(m_db);
	query.exec(selectstr);
	return query;
}

bool QtSqliteTool::isExist(const QString & tableName, const QString & sqlwhere)
{
	QString selectstr = QString("SELECT * FROM %1 WHERE %2").arg(tableName).arg(sqlwhere);
	QSqlQuery query(m_db);
	return query.exec(selectstr) && query.first();
}

bool QtSqliteTool::transaction()
{
	CheckDb
	return m_db.transaction();
}

bool QtSqliteTool::commit()
{
	CheckDb
		return m_db.commit();
}

bool QtSqliteTool::rollback()
{
	CheckDb
		return m_db.rollback();
}

bool QtSqliteTool::setPropertyTable(QString table)
{
	m_propertyTable = table;
	if (m_db.isValid()&&m_db.isOpen()&&!m_db.tables().contains(table))
	{
		return creatTable(QString("CREATE TABLE %1( Key VARCHAR, Val VARCHAR)").arg(m_propertyTable));
	}
	return true;
}

QString QtSqliteTool::property(QString key, QString defaultVal)
{
	if (!m_db.isValid() || !m_db.isOpen())
	{
		return defaultVal;
	}
	
	QString selectstr = QString("SELECT Val FROM %1 WHERE KEY = '%2'").arg(m_propertyTable).arg(key);
	QSqlQuery query(m_db);
	if (query.exec(selectstr) && query.first())
	{
		return query.value(0).toString();
	}
	return defaultVal;
}

bool QtSqliteTool::setProperty(QString key, QString val)
{
	if (!m_db.isValid() || !m_db.isOpen())
	{
		return false;
	}
	if (!m_checkPropertyTable&&!m_db.tables().contains(m_propertyTable))
	{
		creatTable(QString("CREATE TABLE %1( Key VARCHAR, Val VARCHAR)").arg(m_propertyTable));
		m_checkPropertyTable = true;
	}
	QSqlQuery query(m_db);
	QString selectstr = QString("SELECT Val FROM %1 WHERE KEY = '%2'").arg(m_propertyTable).arg(key);
	if (query.exec(selectstr) && query.first())
	{
		QString updatestr = QString("UPDATE %1 SET Val = '%2' WHERE Key = '%3'").arg(m_propertyTable).arg(val).arg(key);
		if (query.exec(updatestr))
			return true;
		else
			m_lasterr = query.lastError().text();
	}
	else
	{
		QString insertstr = QString("INSERT INTO %1 (Key,Val) VALUES ('%2','%3')").arg(m_propertyTable).arg(key).arg(val);
		if (query.exec(insertstr))
			return true;
		else
			m_lasterr = query.lastError().text();
	}
	return false;
}

QString QtSqliteTool::getPropertyTable()
{
	return m_propertyTable;
}

QList QtSqliteTool::queryToList(const QString & tableName, QStringList itemName /*= QStringList()*/, const QString & sqlwhere /*= ""*/, const QString & orderBy /*= ""*/)
{
	QList res;
	if (!m_db.isValid() || !m_db.isOpen() || !tableNames().contains(tableName))
	{
		return res;
	}
	
	if (itemName.isEmpty())
	{//为空时读取全部
		QSqlRecord record = m_db.record(tableName);
		int count = record.count();
		for (int i = 0; i < count; ++i)
		{
			QSqlField field = record.field(i);
			itemName.append(field.name());
		}
	}
	QString selectstr = QString("SELECT ");
	for (int i = 0; i < itemName.size(); i++)
	{
		selectstr.append(i == 0 ? itemName.at(i) : "," + itemName.at(i));
	}
	selectstr.append(QString(" FROM %1").arg(tableName));
	if (!sqlwhere.isEmpty())
	{
		selectstr.append(QString(" WHERE %1").arg(sqlwhere));
	}
	if (!orderBy.isEmpty())
	{
		selectstr.append(QString(" ORDER BY %1").arg(orderBy));
	}
	QSqlQuery query(m_db);
	if (query.exec(selectstr))
	{
		if (query.first())
		{
			do 
			{
				QVariantMap item;
				for (int i = 0; i < itemName.size(); ++i)
				{
					QString fieldName = itemName.at(i);
					item.insert(fieldName, query.value(fieldName));
				}
				res.append(item);
			} while (query.next());
		}
	}
	return res;
}

QSqlRecord QtSqliteTool::record(QString tabName)
{
	return m_db.isValid() ? m_db.record(tabName) : QSqlRecord();
}

static QtSqliteToolManager* g_sqltoolmanager = NULL;
QtSqliteToolManager* QtSqliteToolManager::instance()
{
	if (g_sqltoolmanager==NULL)
	{
		g_sqltoolmanager = new QtSqliteToolManager();
	}
	return g_sqltoolmanager;
}

QtSqliteTool* QtSqliteToolManager::openDb(const QString& dbpath, const QString& guid)
{
	if (m_dbs.contains(guid))
	{
		return m_dbs.value(guid);
	}
	QtSqliteTool* newdb = new QtSqliteTool(dbpath);
	if (!newdb->open())
	{
		delete newdb;
		newdb = NULL;
		return NULL;
	}
	QStringList tablse = newdb->tableNames();
	DbInfo info = m_dbInfos.value(guid);
	
	for (int i = 0; i < info.tableNames.size(); ++i)
	{
		if (!tablse.contains(info.tableNames.at(i)))
			newdb->creatTable(info.tableCreateStrs.at(i));
	}
	m_dbs.insert(guid, newdb);
	return newdb;
}

bool QtSqliteToolManager::closeDB(const QString& dbpath)
{
	for (auto i = m_dbs.begin(); i != m_dbs.end(); ++i)
	{
		if (0 == (i.value())->getDbpath().compare(dbpath))
		{
			(i.value())->close();
			m_dbs.remove(i.key());
			delete i.value();
			return true;
		}
	}
	return false;
}

QtSqliteTool* QtSqliteToolManager::getTool(const QString& guid)
{
	return m_dbs.value(guid, NULL);
}

QtSqliteToolManager::~QtSqliteToolManager()
{
	for (auto i = m_dbs.begin(); i != m_dbs.end(); ++i)
	{
		(i.value())->close();
		delete i.value();
	}
	m_dbs.clear();
}

QtSqliteToolManager::QtSqliteToolManager()
{

}

void DBRegisterAppend(const SqlTableBase& base)
{
	QString guid = base.dbGuid();
	QString create = base.createStr();
	if (guid.isEmpty()||create.isEmpty())
		return;
	if (!QtSqliteToolManager::instance()->m_dbInfos.contains(guid))
		QtSqliteToolManager::instance()->m_dbInfos.insert(guid, DbInfo());
	QtSqliteToolManager::instance()->m_dbInfos[guid].append(base.tableName(),base.createStr());
}

 

 

 

你可能感兴趣的:(c++,Android,c++,数据库,sqlite,Qt,java)