我是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(感谢您的帮助)尝试了我所做的相同的事情,因此对我而言他的工作对我而言是错误的。因此,上面的原始代码实际上是正确的。
最佳答案
我刚刚花时间完全重播了该示例。
这个对我有用。我创建一个这样的数据库:
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)