游戏服务端之C++封装Mysql
2017-02-15 19:56
507 查看
很多缺少实际工作经验的同学会认为,操作MySQL还需要封装?!直接写sql语句操作就可以了。其实封装Mysql有以下的好处:
1、更加安全。即使你是相当谨慎的一个程序员,就算在几百处甚至几千处地方写sql操作Mysql也避免不了会出现写错表名,字段名写错了或者写少写多了,符号写错等等。封装可以解决这些问题。
2、更好的移植性。封装其实就是一些共性的集合,这样当然具有更好的移植性了(这样能方便像我一样的搬运工搬代码了)。
3、更好的可读性。封装一般具有更好的可读性,当然在我接触过的一些代码中,封装了之后,可读性更差了;其可读性主要是封装得难以理解,在看不到源代码的时候,根本不知道这些代码有什么作用。
4、能提高程序效率。我们都知道,IO操作的效率是比较低下,读写数据库也属于IO操作的范畴。一般提高读写Mysql的效率在于在一次IO操作中尽量操作更多的数据。例如批量插入数据(INSERT)。当然不用封装也可以批量操作,只是比较困难。
5、更加容易维护。可以想像一下,当你数据库表结构发生变化的时候,如果你用浅白的sql操作Mysql,你要在每一个使用过的地方都要修改,不但增加了工作量,而且更容易出错。
6、更有效率。这里的效率是开发效率,统合以上几点,不难知道封装能具有更好的开发效率。
(PS:上述的封装是指好的封装,差的封装有可能适得其反)
下面先看一下用例,以查找为例:
数据库表new_table的所有数据
代码的调用
下这里定义了表的结构
#ifndef DATATABLE_H
#define DATATABLE_H
#include "gamemysql.h"
namespace Table
{
GameMysql new_table("new_table");
namespace NEW_TABLE
{
enum Field
{
Name,
Age,
School
};
const char * Fields[] = {"name","age","school"};
}
GameMysql gametime("gametime");
namespace GAMETIME
{
enum Field
{
OpenServerTime,
ActiveDate,
PetLiveTime,
Time
};
const char * Fields[] = {"openservertime","activedate","petlivetime","time"};
}
}
#endif // DATATABLE_H
在这里设置查询条件,一般在游戏当中,只保存整型和字符串。
最后就是执行查询了
unsigned int GameMysql::Find(ALLROWS &rows)
{
HANDLEERROR(0);
if (m_findval == "") m_findval = "*";
if (m_condition[GameMysql::SELECT] == "" )
{
m_sql[GameMysql::SELECT] = "SELECT " + m_findval + " FROM " + m_tablename;
}
else
{
m_sql[GameMysql::SELECT] = "SELECT " + m_findval + " FROM " + m_tablename + " WHERE " + m_condition[GameMysql::SELECT];
m_condition[GameMysql::SELECT] = "";
}
static unsigned int field_len = 0;
if (0 != mysql_query(g_db_handle,m_sql[GameMysql::SELECT] .c_str()))
{
printf("Mysql Find Rows Error...\n");
field_len = 0;
rows.length = 0;
}
else
{
m_data_res = mysql_store_result(g_db_handle);
static MYSQL_ROW row;
while((row = mysql_fetch_row(m_data_res)) != NULL)
{
rows.row.push_back(row);
}
field_len = mysql_num_fields(m_data_res);
rows.length = mysql_num_rows(m_data_res);
mysql_free_result(m_data_res);
}
m_findval = "";
return field_len;
}
当然以上只是提供对Mysql封装的一个思路,也许你有更好的思路!也许之后我不再认为这是一种好设计!
原文地址:http://blog.csdn.net/yitouhan/article/details/17187569
1、更加安全。即使你是相当谨慎的一个程序员,就算在几百处甚至几千处地方写sql操作Mysql也避免不了会出现写错表名,字段名写错了或者写少写多了,符号写错等等。封装可以解决这些问题。
2、更好的移植性。封装其实就是一些共性的集合,这样当然具有更好的移植性了(这样能方便像我一样的搬运工搬代码了)。
3、更好的可读性。封装一般具有更好的可读性,当然在我接触过的一些代码中,封装了之后,可读性更差了;其可读性主要是封装得难以理解,在看不到源代码的时候,根本不知道这些代码有什么作用。
4、能提高程序效率。我们都知道,IO操作的效率是比较低下,读写数据库也属于IO操作的范畴。一般提高读写Mysql的效率在于在一次IO操作中尽量操作更多的数据。例如批量插入数据(INSERT)。当然不用封装也可以批量操作,只是比较困难。
5、更加容易维护。可以想像一下,当你数据库表结构发生变化的时候,如果你用浅白的sql操作Mysql,你要在每一个使用过的地方都要修改,不但增加了工作量,而且更容易出错。
6、更有效率。这里的效率是开发效率,统合以上几点,不难知道封装能具有更好的开发效率。
(PS:上述的封装是指好的封装,差的封装有可能适得其反)
下面先看一下用例,以查找为例:
数据库表new_table的所有数据
代码的调用
#include <stdio.h> #include <time.h> #include "globalvariable.h" #include "luaengine.h" #include "gamesocket.h" #include "log.h" #include "dll.h" #include "MyDll.h" #include "gametime.h" #include "frame.h" #include "datatable.h" #include "showcrash.h" #include "globalfunction.h" int main() { GameMysql::ALLROWS rows; int fieldlen = Table::new_table.Find(rows); for (int i = 0; i < rows.length; ++i) { for(int j =0; j< fieldlen; ++j) { printf("%s\t",rows.row[i][j]); } printf("\n"); } GameMysql::ClearAllRows(rows); printf("\nadd a condition.....\n"); Table::new_table.SetSelectCondition(Table::NEW_TABLE::Fields[Table::NEW_TABLE::Age],99,GameMysql::EQ); fieldlen = Table::new_table.Find(rows); for (int i = 0; i < rows.length; ++i) { for(int j =0; j< fieldlen; ++j) { printf("%s\t",rows.row[i][j]); } printf("\n"); } GameMysql::ClearAllRows(rows); printf("\nadd more a condition.....\n"); Table::new_table.SetSelectCondition(Table::NEW_TABLE::Fields[Table::NEW_TABLE::Age],99,GameMysql::EQ,false); Table::new_table.SetSelectCondition(Table::NEW_TABLE::Fields[Table::NEW_TABLE::School],"XX大学",GameMysql::EQ); fieldlen = Table::new_table.Find(rows); for (int i = 0; i < rows.length; ++i) { for(int j =0; j< fieldlen; ++j) { printf("%s\t",rows.row[i][j]); } printf("\n"); } return 0; }
下这里定义了表的结构
#ifndef DATATABLE_H
#define DATATABLE_H
#include "gamemysql.h"
namespace Table
{
GameMysql new_table("new_table");
namespace NEW_TABLE
{
enum Field
{
Name,
Age,
School
};
const char * Fields[] = {"name","age","school"};
}
GameMysql gametime("gametime");
namespace GAMETIME
{
enum Field
{
OpenServerTime,
ActiveDate,
PetLiveTime,
Time
};
const char * Fields[] = {"openservertime","activedate","petlivetime","time"};
}
}
#endif // DATATABLE_H
在这里设置查询条件,一般在游戏当中,只保存整型和字符串。
void GameMysql::SetSelectCondition( string field, int val, unsigned int r, bool isend /*= true*/ ,unsigned int c) { CHECKRELATION(r); CHECKCONNECT(c); SETTEMP(connect[c]); static char str_val[32]; sprintf(str_val,"%d",val); m_condition[GameMysql::SELECT] = m_condition[GameMysql::SELECT] + field + relation[r] +str_val + temp; } void GameMysql::SetSelectCondition( string field, string val, unsigned int r, bool isend /*= true*/ ,unsigned int c) { CHECKRELATION(r); CHECKCONNECT(c); SETTEMP(connect[c]); m_condition[GameMysql::SELECT] = m_condition[GameMysql::SELECT] + field + relation[r] + "'" + val + "'" + temp; }
最后就是执行查询了
unsigned int GameMysql::Find(ALLROWS &rows)
{
HANDLEERROR(0);
if (m_findval == "") m_findval = "*";
if (m_condition[GameMysql::SELECT] == "" )
{
m_sql[GameMysql::SELECT] = "SELECT " + m_findval + " FROM " + m_tablename;
}
else
{
m_sql[GameMysql::SELECT] = "SELECT " + m_findval + " FROM " + m_tablename + " WHERE " + m_condition[GameMysql::SELECT];
m_condition[GameMysql::SELECT] = "";
}
static unsigned int field_len = 0;
if (0 != mysql_query(g_db_handle,m_sql[GameMysql::SELECT] .c_str()))
{
printf("Mysql Find Rows Error...\n");
field_len = 0;
rows.length = 0;
}
else
{
m_data_res = mysql_store_result(g_db_handle);
static MYSQL_ROW row;
while((row = mysql_fetch_row(m_data_res)) != NULL)
{
rows.row.push_back(row);
}
field_len = mysql_num_fields(m_data_res);
rows.length = mysql_num_rows(m_data_res);
mysql_free_result(m_data_res);
}
m_findval = "";
return field_len;
}
当然以上只是提供对Mysql封装的一个思路,也许你有更好的思路!也许之后我不再认为这是一种好设计!
原文地址:http://blog.csdn.net/yitouhan/article/details/17187569
相关文章推荐
- 游戏服务端之C++封装Mysql
- C++连接MySQL的另一个封装库MySQL++
- C++操作MYSQL(封装成DLL)
- 用C++封装MySQL的API的教程
- C++封装 mysql C api遇到的问题
- 为什么多数游戏服务端是用 C++ 来写
- 在vc中通过连接池操作mysql(api方式),附c++访问mysql的封装类
- [C++]MYSQL 数据库操作封装及连接池实现
- C++实现的分布式游戏服务端引擎KBEngine详解
- mysql Connector C/C++ 多线程封装
- MySQL的C++封装实现数据库的创建,表的创建,数据库的读写操作
- C++游戏服务端 技术交流群 (申请最好两年以上经验) 群号91870847
- 游戏服务端之C++游戏服务端防崩溃
- 用C++封装MySQL的API的教程
- MySQL的C++封装
- html5和c++封装webkit内核实现开放式游戏大厅设计(一)
- 游戏服务端IOCP模型,自己封装的一个类,3行代码搞定服务端。
- C++封装MySql接口
- MySQL的C++封装
- 游戏服务端之C++网络库对外接口