A realtion 1 to 1 is not created properly.

Forum for posting problems using QxOrm library

A realtion 1 to 1 is not created properly.

Postby jduran » Mon May 14, 2012 5:19 pm

Dear all,

I'm new to this forum. My name is Joaquim Duran. Currently, I'm working with the version 1.2.4 BETA 17 in linux, using g++ 4.6.1.

I've written to classes with a relation 1 to 1 between them. I've no idea I've written something wrong, but I've the impression that the relation is not well implemented.

Class Appointment:

Code: Select all
class AbsInfo;

class Appointment
{
   QX_REGISTER_FRIEND_CLASS(Appointment)

public:
   typedef boost::shared_ptr<AbsInfo> PtrAbsInfo;

   Appointment();
    virtual ~Appointment();

    void set_id(long id) { m_id = id; };
    long get_id() const { return m_id; };

    void set_info(PtrAbsInfo info) { m_info = info; };
    const PtrAbsInfo get_info() const { return m_info; };
    PtrAbsInfo get_info() { return m_info; };

private:
    long m_id;
    PtrAbsInfo m_info;
};

QX_REGISTER_HPP_MY_TEST_EXE(Appointment, qx::trait::no_base_class_defined, 0)


Code: Select all
QX_REGISTER_HPP_MY_TEST_EXE(Appointment, qx::trait::no_base_class_defined, 0)

typedef boost::shared_ptr<Appointment> PtrAppoint;
typedef qx::QxCollection<int, PtrAppoint> CollectionAppoint;


QX_REGISTER_CPP_MY_TEST_EXE(Appointment)

// Mapping to database
namespace qx
{
template <> void register_class(QxClass<Appointment> & t)
{
   t.id(&Appointment::m_id, "cita_id");

   t.relationOneToOne(&Appointment::m_info, "info_id");
}
}


// Class implementation
Appointment::Appointment():
    m_id(0),
    m_info()
{
}


Appointment::~Appointment()
{
}



Class AbsInfo:

Code: Select all
class Appointment;

class AbsInfo
{
   QX_REGISTER_FRIEND_CLASS(AbsInfo)

public:
    enum Type
    {
        DICOM,      // DICOM
        HL7,        // HL5
        WEB_SERVICE   // Gem Med Web service
    };

    typedef boost::shared_ptr<Appointment> PtrAppoint;

    AbsInfo();
    virtual ~AbsInfo();

    void set_id(long id) { m_id = id; };
    long get_id() const { return m_id; };

    void set_appoint(PtrAppoint appoint) { m_appoint = appoint; };
    const PtrAppoint get_appoint() const { return m_appoint; };
    PtrAppoint get_appoint() { return m_appoint; };

private:
    long m_id;
    PtrAppoint m_appoint;
};

QX_REGISTER_HPP_MY_TEST_EXE(AbsInfo, qx::trait::no_base_class_defined, 0)


Code: Select all
QX_REGISTER_CPP_MY_TEST_EXE(AbsInfo)

// Mapping to database
namespace qx
{
template <> void register_class(QxClass<AbsInfo> & t)
{
   t.id(&AbsInfo::m_id, "info_id");

   t.relationOneToOne(&AbsInfo::m_appoint, "appoint_id");
}
}


// Class implementation
AbsInfo::AbsInfo() :
   m_id(0), m_appoint()
{
}


AbsInfo::~AbsInfo()
{
}


Sql sequence to create the table:

Code: Select all
[QxOrm] sql query (107 ms) : CREATE TABLE Appointment (cita_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT)
[QxOrm] sql query (99 ms) : CREATE TABLE AbsInfo (info_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT)


None of the tables contains have any external key.

Could you tell me how can I fix the problem?

Thanks and Best Regards,
Joaquim Duran
jduran
 

Re: A realtion 1 to 1 is not created properly.

Postby QxOrm admin » Mon May 14, 2012 8:23 pm

Hi, and welcome on this forum !

A relation one-to-one is rarely used in a real program.
In almost all cases, you have to define a many-to-one and/or one-to-many relationship, see qxBlog tutorial for examples :
- one-to-many : http://www.qxorm.com/qxorm_en/tutorial.html#tuto_6
- many-to-one : http://www.qxorm.com/qxorm_en/tutorial.html#tuto_7

A one-to-one relationship is like inheritance in object concept : this is when 2 tables share the same ID.
For example, a Person table and a User table could share the same ID into database because a user could be considered as a person => this is a one-to-one relationship.

Note : be careful, use qx::dao::create_table<T> function only for prototypes !
To create your database schema, you have to write your own function using introspection engine of QxOrm library.
It's very easy to do, you can find 2 examples on the FAQ of QxOrm library here :
- http://www.qxorm.com/qxorm_en/faq.html#faq_230
- qx::QxClassX::dumpSqlSchema() method : http://www.qxorm.com/qxorm_en/resource/ ... chema.html
QxOrm admin
 

Re: A realtion 1 to 1 is not created properly.

Postby jduran » Tue May 15, 2012 11:36 am

Hello,

Thanks for your reply, including the suggestions. I would like to remark two points:

1. - In the previous sample, I've replaced the 1 to 1 to 1 to N relation. When trying to insert a new appointment, an error has been detected caused by a bad SQL sentence due to the lack of additional fields in the table.

Code: Select all
[QxOrm] sql query (119 ms) : CREATE TABLE Appointment (appoint_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT)
[QxOrm] sql query (92 ms) : CREATE TABLE AbsInfo (info_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, appoint_id INTEGER)
[QxOrm] execute sql query failed : INSERT INTO Appointment) VALUES)


I've added a description to the Appointment class, with the corresponding mapping to the table and that the problem has been solved.

2. - To restrict a 1 to N relation to a 1 to 1, the external key of the relation (AbsInfo.appoint_id in the previous example) could be declared as UNIQUE.

As a example of a 1 to 1 relation, I'm thinking in a transportation company, where the company have trucks and hire drivers, where each truck could have a driver and a driver could drive a truck. Trucks and drivers are different entities.

Joaquim Duran
jduran
 

Re: A realtion 1 to 1 is not created properly.

Postby QxOrm admin » Tue May 15, 2012 12:33 pm

1. ... I've added a description to the Appointment class, with the corresponding mapping to the table and that the problem has been solved.

Yes you can't have a table with only 1 column corresponding to a auto-increment ID !
Suppress auto-increment or create at least 1 column to store something (as you made ;) ).

2. - To restrict a 1 to N relation to a 1 to 1, the external key of the relation (AbsInfo.appoint_id in the previous example) could be declared as UNIQUE.
As a example of a 1 to 1 relation, I'm thinking in a transportation company, where the company have trucks and hire drivers, where each truck could have a driver and a driver could drive a truck. Trucks and drivers are different entities.

From QxOrm library point of vue, a 1-1 relationship is like inheritance in object concept (as I said in my previous message).
This is why you have to register a n-1 relationship.
You can add the UNIQUE keyword in your SQL schema if you want.

As it is written on the FAQ, I recommend to manage the database (create and modify tables) with a tool provided by the SGBD.
But if you want to manage yourself by code the UNIQUE keyword, you can use the concept of property bag registering your class : http://www.qxorm.com/doxygen/html/class ... y_bag.html
For example, in your qx::register_class<T> function :
Code: Select all
// ...
pData = t.data(& myClass::m_myProperty, "my_property");
pData->setPropertyBag("UNIQUE", "1");
// ...

And then, when you use introspection engine to iterate over each properties to create your SQL schema, you can check the "UNIQUE" property bag, like this :
Code: Select all
// ...
QString sUnique = p->getPropertyBag("UNIQUE").toString();
if (sUnique == "1")
{
   // Add UNIQUE keyword to your SQL schema...
}
QxOrm admin
 

Re: A realtion 1 to 1 is not created properly.

Postby jduran » Tue May 15, 2012 1:44 pm

Thanks for your comments.

Joaquim Duran
jduran
 


Return to QxOrm - Help

Who is online

Users browsing this forum: No registered users and 5 guests