我比较熟悉c ++,mysql和boost ......
我正在尝试使用BLOB将c ++对象存储在mySQL数据库中。
我正在使用boost :: archive来序列化和反序列化我的对象。
存储blob似乎工作正常,但是当我尝试反序列化结果blob时,我的程序崩溃了。 我真的会暗示如何使这项工作成功。
我的目标是存储更复杂的对象,但就目前而言,我正在尝试使用一个非常简单的类:
class user
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & id_;
ar & name_;
ar & age_;
}
int id_;
std::string name_;
int age_;
public:
user () {};
user (int id,std::string name, int age)
{
id_ = id;
name_ = name;
age_ = age;
};
int id(){
return id_;
};
std::string name(){
return name_;
};
int age(){
return age_;
};
};
这是主要功能:
int main(){
// a test object
user u1(1,"myName",20);
// serialization
std::stringstream str;
{
boost::archive::binary_oarchive oa(str);
oa << u1;
}
//mysql
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *sqlRes;
sql::PreparedStatement *prep_stmt;
try {
/* Create a connection */
driver = get_driver_instance();
con = driver-> connect("tcp://127.0.0.1:3306", "root", "mypass");
stmt = con->createStatement();
//test database with a table named users containing only one column, a BLOB(10000)
stmt->execute("use test");
prep_stmt = con -> prepareStatement ("insert into users(obj) VALUES(?)");
prep_stmt->setBlob(1,&str);
prep_stmt->execute();
}
catch (sql::SQLException &e) {
//some stuff...
(...)
}
//Reading the only element in the table
sqlRes = stmt->executeQuery("select * from users");
sqlRes->next();
std::istream *blobdata = sqlRes->getBlob(1);
//trying to deserialize the blob...
user newUser;
{
boost::archive::binary_iarchive ia(*blobdata); //crashes at this line
ia >> newUser;
}
//If it worked, we should see our original user data...
cout << "id = "<< newUser.id() <<endl;
cout << "name = "<< newUser.name() <<endl;
cout << "aeg = "<< newUser.age() <<endl;
return 0;
}
我知道我可能做的事情非常糟糕,但我无法理解!
请帮帮我,谢谢。
编辑1:
getBlob()返回null_ptr,我不知道为什么。
如果我这样做而不是让对象回来:
std::stringstream ss;
ss << sqlRes->getString(1);
user newUser;
{
boost::archive::binary_iarchive ia(ss);
ia >> newUser;
}
它工作正常并且对象被正确恢复......不确定它是否适用于更复杂的对象。
编辑2:
事实证明,在我的环境中出现了一些问题,因为@sehe(感谢你的帮助)尝试了我做的同样的事情并且对他有用。所以上面的原始代码实际上是正确的。
答案 0 :(得分:1)
我刚刚花时间完全重播了这个例子。
它对我有用。我创建了这样一个数据库:
create database test;
use test;
create table users (obj mediumblob NULL);
我编译以下程序(根据需要替换数据库用户/名称):
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <cppconn/driver.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/exception.h>
#include <sstream>
#include <iostream>
class user
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & id_;
ar & name_;
ar & age_;
}
int id_;
std::string name_;
int age_;
public:
user () {};
user (int id,std::string name, int age)
{
id_ = id;
name_ = name;
age_ = age;
};
int id(){
return id_;
};
std::string name(){
return name_;
};
int age(){
return age_;
};
};
int main(){
// a test object
user u1(1,"myName",20);
// serialization
std::stringstream str;
{
boost::archive::binary_oarchive oa(str);
oa << u1;
}
//mysql
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *sqlRes;
sql::PreparedStatement *prep_stmt;
try {
/* Create a connection */
driver = get_driver_instance();
con = driver-> connect("tcp://127.0.0.1:3306", "root", "*********");
stmt = con->createStatement();
//test database with a table named users containing only one column, a BLOB(10000)
stmt->execute("use test");
prep_stmt = con -> prepareStatement ("insert into users(obj) VALUES(?)");
prep_stmt->setBlob(1,&str);
prep_stmt->execute();
}
catch (sql::SQLException &e) {
//some stuff...
exit(255);
}
//Reading the only element in the table
sqlRes = stmt->executeQuery("select * from users");
sqlRes->next();
std::istream *blobdata = sqlRes->getBlob(1);
//trying to deserialize the blob...
user newUser;
{
boost::archive::binary_iarchive ia(*blobdata); //crashes at this line
ia >> newUser;
}
//If it worked, we should see our original user data...
std::cout << "id = " << newUser.id() << std::endl;
std::cout << "name = " << newUser.name() << std::endl;
std::cout << "aeg = " << newUser.age() << std::endl;
return 0;
}
注意这会泄漏资源。你会想要解决这个问题。
运行时,会打印
sehe@desktop:/tmp$ ./test
id = 1
name = myName
aeg = 20
mysql显示:
mysql> select * from users;
+---------------------------------------------------------------------+
| obj |
+---------------------------------------------------------------------+
| serialization::archive
myName |
+---------------------------------------------------------------------+
1 row in set (0.00 sec)