c++ boost::archives和mySql BLOB,反序列化错误

标签 c++ mysql serialization boost blob

我对 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)

关于c++ boost::archives和mySql BLOB,反序列化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27925018/

相关文章:

php、mysql 和 phpmyadmin、MAMP 或 Homebrew 软件

c# - 实现 PropertyChangedBase 时的 caliburn.micro 序列化问题

c# - C# 的垃圾收集会导致实时音频应用程序出现问题吗?

c++ - spaceship 运算符(operator)是否有std::less/std::greater?

c++ - 在 C++ 中连接两个 char* 的函数

c++ - "The program can' t 启动,因为您的计算机中缺少 opencv_world300.dll“C++ 中的错误

mysql - DOUBLE 列上的最大 auto_increment 值是多少?

php - 插入多对多关系设置

c# - 如果名称为大写,Newtonsoft JsonConvert.SerializeObject 将忽略 JsonProperty

java - 使用 jackson 在 java 中嵌套自定义反序列化