AW: [odb-users] Multi-Database Support - Cannot integrate Multi-Database Support / Bug report for the compiler: odb-2.2.1-i686-windows

Benjamin Schudel benjamin.schudel at nexirius.com
Thu May 23 09:44:55 EDT 2013


Hi Boris,

you will find the classes as attachments.

Thanks in advance,

Benjamin


-----Ursprüngliche Nachricht-----
Von: Boris Kolpackov [mailto:boris at codesynthesis.com]
Gesendet: Donnerstag, 23. Mai 2013 15:11
An: Benjamin Schudel
Cc: odb-users at codesynthesis.com
Betreff: Re: [odb-users] Multi-Database Support - Cannot integrate
Multi-Database Support / Bug report for the compiler:
odb-2.2.1-i686-windows

Hi Benjamin,

Benjamin Schudel <benjamin.schudel at nexirius.com> writes:

> Now we stumble over a compile problem, which somehow seems to be
> related to the use of inheritance of the persisted classes. The
> Compiler complains of a missing static member 'table_name' within our
> abstract base class (BaseBO).

Can you send me the definition of the BaseBO class (and maybe one of its
derived classes as well, e.g., User)? Or, better yet, a small but complete
test that reproduces the problem.

Boris
-------------- next part --------------
///////////////////////////////////////////////////////////
//  User.h
//  Implementation of the Class User
//  Created on:      29-Nov-2012 18:20:21
//  Original author: David Posva
///////////////////////////////////////////////////////////

#if !defined(EA_0FA84639_6280_4cf2_B369_4E88785C6532__INCLUDED_)
#define EA_0FA84639_6280_4cf2_B369_4E88785C6532__INCLUDED_

#include "BaseBO.h"
#include "UserGroup.h"
#include <vector>

#ifndef ODB_COMPILER
#include "LogManager.h"
#include "DatabaseManager.h"
#endif

//#pragma db value(QString) type("VARCHAR")

#pragma db object pointer(shared_ptr)
#pragma db object optimistic
class User :
#ifndef ODB_COMPILER
	public std::enable_shared_from_this< User >, 
#endif
	public BaseBO
{

public:
	User();
	User(QString name, QString password);
	virtual ~User();

	vector<shared_ptr<UserGroup> > getGroups() const;
	void setGroups(vector<shared_ptr<UserGroup> > val);
	QString getName() const;
	void setName(QString val);
	QString getPassword() const;
	void setPassword(QString val);

	virtual void save();
	virtual void remove();

private:
	friend class odb::access;

	vector<shared_ptr<UserGroup> > groups;
	QString name;
	QString password;

#ifndef ODB_COMPILER
	#pragma db transient
	shared_ptr<LogManager> log;

	#pragma db transient
	shared_ptr<DatabaseManager> dbManager;
#endif
};
#endif // !defined(EA_0FA84639_6280_4cf2_B369_4E88785C6532__INCLUDED_)
-------------- next part --------------
///////////////////////////////////////////////////////////
//  BaseBO.h
//  Implementation of the Class BaseBO
//  Created on:      27-Nov-2012 18:49:06
//  Original author: David Posva
///////////////////////////////////////////////////////////

#if !defined(EA_741592B4_4C31_44b7_9FD1_A2299286834F__INCLUDED_)
#define EA_741592B4_4C31_44b7_9FD1_A2299286834F__INCLUDED_

#define NOMINMAX
#include "BoIF.h"
#ifndef ODB_COMPILER
#include "Uuid.h"
#include "LogManager.h"
#include "ObjectSerializeContainerIF.h"
#endif

#ifdef ODB_COMPILER
#include <odb/core.hxx>
#endif

#include <vector>
#include <iostream>

#include <QtCore/QString>
#include <QtCore/QDateTime>
#include <odb/tr1/memory.hxx>
//#include <memory>
using std::tr1::shared_ptr;
//using std::shared_ptr;
using std::vector;
using std::cerr;
//using odb::tr1::lazy_shared_ptr; //no odb lazy loading -> use hand made delayed loading, so it works also with detached objects

//#pragma warning (push)
//#pragma warning (disable:4068)

//#pragma db value(Uuid) type("VARCHAR")
#pragma db value(QString) type("VARCHAR") mysql:type("VARCHAR(100)")
#pragma db value(QDateTime) type("DATETIME") sqlite:type("TEXT")
//
#pragma db object /*pointer(*)*/ abstract
#pragma db object optimistic
/**
* Base implementation of all Business Objects.
*/
/*abstract*/ class BaseBO : public BoIF
{
	friend class BoLoaderFactory;

protected:
	//BaseBO(Uuid id);

public:
	BaseBO();
	virtual ~BaseBO();

#ifndef ODB_COMPILER
	#pragma db transient
	virtual void serialize(ObjectSerializeContainerIF* output); //impl BoIF
	virtual void deserialize(ObjectSerializeContainerIF* input); //impl BoIF
	virtual void save() = 0;
	virtual void remove() = 0;
#endif
	//#pragma db transient
	//virtual QString toString();

	//TODO ref to db connection / bo source
	//not via singleton to DbConnection => to be able to have more than one BO sources in one application

	/**
	 * The ID for the BO.
	 * Consisting of a random UUID - with first 3 chars for the class identifier.
	 */
	virtual QString get_id() const; //impl BoIF //lazy initializer -> fixing the "wrong type in base c'tor" issue - and saving some time if never used
	void setReadOnly(bool readOnly);
	bool getReadOnly();
	void setPersistable(bool persistable);
	bool getPersistable();
	void setPersisted(bool persisted);
	bool getPersisted();
	void setDeleted(bool deleted);
	bool getDeleted();
	void setCreationDate(QDateTime creationDate);
	QDateTime getCreationDate();
	void setCreationUser(QString creationUser);
	QString getCreationUser();
	void setModificationDate(QDateTime modificationDate);
	QDateTime getModificationDate();
	void setModificationUser(QString modificationUser);
	QString getModificationUser();
	int getVersionNr();

private:
	friend class odb::access;

	/**
	 * Random UUID - with first 3 chars for the class identifier.
	 */
	#pragma db id type("VARCHAR") mysql:type("VARCHAR(100)")
	#pragma db get(get_id) // Uses by-reference modifier.
	mutable QString id; //UUId-String from Uuid::createUuidString()

	bool readOnly;
	/**
	 * Can be stored into the DB. (see also persisted & deleted)
	 * BOs that should get written into the DB (due to no mapping to a table or because they are just temporary) should get constructed with false.
	 */
	bool persistable;
	/**
	 * is already in the DB
	 */
	bool persisted;
	bool deleted;
	/**
	 * -> does also set the modificationDate (if that is null)
	 */
	QDateTime creationDate;
	/**
	 * "weak" reference to the user - via name not via userId.
	 * -> does also set the modificationUser (if that is null)
	 */
	QString creationUser;
	/**
	 * is >= creationDate = never null
	 */
	QDateTime modificationDate;
	/**
	 * "weak" reference to the user - via name not via userId.
	 * if modificationDate == creationDate -> modificationUser == creationUser
	 */
	QString modificationUser;
	
	/**
	 * Used to compare if the version in the DB is the one that was loaded.
	 * Will be automatically incremented everytime it is stored. See Chapter 11 "Optimistic Concurrency" #pragma db version
	 * If the version isn't the same as the one in memory a reload is needed & a save must be prohibited.
	 * (= someone else was faster with changing and writing the data => odb::object_changed exception - "catch (const object_changed&)")
	 * The initialization and increment is managed by ODB. A value of 0 means = not saved yet / transient.
	 * ! Don't change this value in business logic!!!
	 */
	#pragma db version
	const unsigned int versionNr; //!const is NOT forced by ODB: see chapter 11 Optimistic Concurrency

	///*abstract*/ list</*Property*/QString>* getProperties();

#ifndef ODB_COMPILER
	#pragma db transient
	shared_ptr<LogManager> log;
#endif

};

#endif // !defined(EA_741592B4_4C31_44b7_9FD1_A2299286834F__INCLUDED_)
-------------- next part --------------
///////////////////////////////////////////////////////////
//  BaseBO.cpp
//  Implementation of the Class BaseBO
//  Created on:      29-Nov-2012 18:20:07
//  Original author: David Posva
///////////////////////////////////////////////////////////

#include "BaseBO.h"
#include "Uuid.h"
#include "ObjectSerializeContainerIF.h"
#include "Exception.h"

//BaseBO::BaseBO(Uuid existingId){
//	idx = existingId;
//}
//QString BaseBO::toString(){
//	return QString::number(idx);
//}

BaseBO::BaseBO()
	://id(Uuid::createUuidString(QString(typeid(this).name()))),
	creationDate(QDateTime::currentDateTime()),
	modificationDate(QDateTime::currentDateTime()),
	creationUser(QString("me")),
	modificationUser(QString("me")),
	versionNr(0),
	persisted(false),
	deleted(false)
{
	log = LogManager::getCentralInstance();
}

BaseBO::~BaseBO(){

}

void BaseBO::serialize(ObjectSerializeContainerIF* output) {
	log->log(QString("BaseBO::serialize").append(" type: ").append(typeid(*this).name()));
	output->writeAttribute("id",get_id(),true);
	output->writeAttribute("readOnly",readOnly);
	output->writeAttribute("persistable",persistable);
	output->writeAttribute("persisted",persisted);
	output->writeAttribute("deleted",deleted);
	output->writeAttribute("creationDate",creationDate);
	output->writeAttribute("creationUser",creationUser);
	output->writeAttribute("modificationDate",modificationDate);
	output->writeAttribute("modificationUser",modificationUser);
	output->writeAttribute("versionNr",versionNr);
}

void BaseBO::deserialize(ObjectSerializeContainerIF* input){
	log->log(QString("BaseBO::deserialize").append(" type: ").append(typeid(*this).name()));
	this->id = input->readAttribute("id");
	this->readOnly = input->readAttributeBool("readOnly");
	this->persistable = input->readAttributeBool("persistable");
	this->persisted = input->readAttributeBool("persisted");
	this->deleted = input->readAttributeBool("deleted");
	this->creationDate = input->readAttributeQDateTime("creationDate");
	this->creationUser = input->readAttribute("creationUser");
	this->modificationDate = input->readAttributeQDateTime("modificationDate");
	this->modificationUser = input->readAttribute("modificationUser");

	//TODO check does this work?! this->versionNr const_cast - !const is NOT forced by ODB, but suggested: see chapter 11 Optimistic Concurrency
	//http://stackoverflow.com/questions/583076/c-c-changing-the-value-of-a-const
	//http://stackoverflow.com/questions/357600/is-const-cast-safe
	//http://www.cplusplus.com/forum/general/17155/

	unsigned int versionNrDeserialized = input->readAttributeUInt("versionNr");
	//log->log(this->versionNr);
	//log->log(versionNrDeserialized);
	unsigned int * versionNr_Ptr = const_cast<unsigned int* > (&this->versionNr);
	*versionNr_Ptr = versionNrDeserialized;
	//log->log(this->versionNr); //it seems to work with M$-VisualStudio compiler...
}

void BaseBO::save(){
	throw new Exception("BaseBO::save not implemented!");
}

void BaseBO::remove(){
	throw new Exception("BaseBO::remove not implemented!");
}

QString BaseBO::get_id() const {
	//lazy initializer -> fixing the "wrong type in base c'tor" (type is always BaseBO) issue - and saving some time if never used
	// - with id / UUID generation in BaseBO we had: "!derived classes have to overload empty c'tor including idx = Uuid::createUuidString(idx,QString(typeid(this).name())); because the typeid(this) in the baseBO is still BaseBO and not the later type!"
	if (id.length()==0) {
		log->log("id old");
		log->log(id);
		//mutable QString id; -> nicht mehr nötig: const_cast<BaseBO*>(this)->id = Uuid::createUuidString(QString(typeid(*this).name()));
		//id = Uuid::createUuidString(QString(typeid(*this).name()));
		id = Uuid::createUuidString(QString(typeid(*this).name()));
		log->log("id new");
		log->log(id);
	}
	return id;
}

void BaseBO::setReadOnly( bool readOnly )
{
	this->readOnly = readOnly;
}

bool BaseBO::getReadOnly()
{
	return this->readOnly;
}

void BaseBO::setPersistable( bool persistable )
{
	this->persistable = persistable;
}

bool BaseBO::getPersistable()
{
	return this->persistable;
}

void BaseBO::setPersisted( bool persisted )
{
	this->persisted = persisted;
}

bool BaseBO::getPersisted()
{
	return this->persisted;
}

void BaseBO::setDeleted( bool deleted )
{
	this->deleted = deleted;
}

bool BaseBO::getDeleted()
{
	return this->deleted;
}

void BaseBO::setCreationDate( QDateTime creationDate )
{
	this->creationDate = creationDate;
}

QDateTime BaseBO::getCreationDate()
{
	return this->creationDate;
}

void BaseBO::setCreationUser( QString creationUser )
{
	this->creationUser = creationUser;
}

QString BaseBO::getCreationUser()
{
	return this->creationUser;
}

void BaseBO::setModificationDate( QDateTime modificationDate )
{
	this->modificationDate = modificationDate;
}

QDateTime BaseBO::getModificationDate()
{
	return this->modificationDate;
}

void BaseBO::setModificationUser( QString modificationUser )
{
	this->modificationUser = modificationUser;
}

QString BaseBO::getModificationUser()
{
	return this->modificationUser;
}

int BaseBO::getVersionNr()
{
	return this->versionNr;
}

//list</*Property*/QString>* BaseBO::getProperties(){
//	return new list<QString>();
//}
-------------- next part --------------
///////////////////////////////////////////////////////////
//  User.cpp
//  Implementation of the Class User
//  Created on:      29-Nov-2012 18:20:21
//  Original author: David Posva
///////////////////////////////////////////////////////////

#include "User.h"
#include "User-odb.hxx"
#include "Transaction.h"
#include "Exception.h"
#include "SoapServiceManager.h"


User::User(){
	log = LogManager::getCentralInstance();
	dbManager = DatabaseManager::getUniqueInstance();
}

User::User(QString name, QString password) : name(name), password(password){
	log = LogManager::getCentralInstance();
	dbManager = DatabaseManager::getUniqueInstance();
}

User::~User(){

}

void User::save(){
	try
	{
		if (SettingsManager::getUniqueInstance()->getDirectDbConnection()) {
			log->log(QString("Persist User. -> direct in DB"));
			shared_ptr<odb::database> db (dbManager->openDatabaseConnection());
			Transaction t(db);
			if(this->getPersisted())
			{
				db->update(*this);
			}
			else
			{
				this->setPersisted(true);
				db->persist(*this);
			}
			t.commit();
			log->log(QString("User persisted"));
		} else {
			log->log(QString("Persist User. -> via SOAP"));
			SoapServiceManager::getUniqueInstance()->doBusinessTask(this->shared_from_this(), "save");
		}
	}
	catch (const Exception& e)
	{
		cerr << e.what() << endl;
		log->log("save User Exception: ");
		log->log(e.getProblem());
	}
	catch (const odb::exception& e)
	{
		cerr << e.what() << endl;
		log->log("save User Exception: ");
		log->log(e.what());
	}
	catch (const std::exception& e)
	{
		cerr << e.what() << endl;
		log->log("save User Exception: ");
		log->log(e.what());
	}
}

void User::remove()
{
	try
	{
		if (SettingsManager::getUniqueInstance()->getDirectDbConnection()) {
			shared_ptr<odb::database> db (dbManager->openDatabaseConnection());
			Transaction t(db);
			log->log(QString("Remove User. -> direct in DB"));
			db->erase(*this);
			t.commit();
		} else{
			log->log(QString("Remove User. -> via SOAP"));
			SoapServiceManager::getUniqueInstance()->doBusinessTask(this->shared_from_this(), "remove");
		}
	}
	catch (const Exception& e)
	{
		cerr << e.what() << endl;
		log->log("remove User Exception: ");
		log->log(e.getProblem());
	}
	catch (const odb::exception& e)
	{
		cerr << e.what() << endl;
		log->log("remove User Exception: ");
		log->log(e.what());
	}
	catch (const std::exception& e)
	{
		cerr << e.what() << endl;
		log->log("remove User Exception: ");
		log->log(e.what());
	}
}

vector<shared_ptr<UserGroup> > User::getGroups() const
{
	return groups;
}

void User::setGroups( vector<shared_ptr<UserGroup> > val )
{
	groups = val;
}

QString User::getName() const
{
	return name;
}

void User::setName( QString val )
{
	name = val;
}

QString User::getPassword() const
{
	return password;
}

void User::setPassword( QString val )
{
	password = val;
}


More information about the odb-users mailing list