[odb-users] Composite object id with a to-many relationship

Boris Kolpackov boris at codesynthesis.com
Fri Nov 15 03:49:07 EST 2013


Hi Romain,

Romain Gros <grosr.romain at gmail.com> writes:

> The fact is that I cannot specify, in the inverse pragma member, something
> like that: inverse(_idobjectspecification._idinstance), which would be
> perfect for me.

Conceptually, what you are trying to do is use a foreign key as part
of the primary key, or, in ODB terms, use an object pointer as part
of an object id:

#pragma db value
class ObjectSpecificationId
{
private:
  std::shared_ptr<ObjectInstance> _idinstance;
  int _idspecification;
};

ODB currently does not support this and I am not sure we will support
it in the future because of the extra complexity involved.


> To simulate the fact that we can access the
> ObjectSpecificationId::_idinstance, I use a reference to the ObjectInstance
> in the ObjectSpecification (as shown above).
> The thing work well for the load, but with that, I cannot insert new
> ObjectSpecification, because the persist_statement generated defines two
> times the idinstance and cause an MySQL error:
> "INSERT INTO `ObjectSpecification` "
>   "(`idinstance`, "
>   "`idspecification`, "
>   "`value`, "
>   "`idinstance`) "
>   "VALUES "
>   "(?, ?, ?, ?)";

Right. You basically mapped two data members to the same column, which
won't work.


> Do you know a good way to do that?

I think the best way is to keep it simple and just duplicate the
ObjectInstance id in both the ObjectSpecification id and the
pointer. You will incur a small overhead by storing the same
value in two columns, but other than that, things will be nice
and simple.


> Also, a solution that I didn't try yet is the use of the post_load
> callback, but if I do that, I'm afraid that I won't be able to use
> lazy_ptr, right ?

No, this won't work because of the inverse() pragma in ObjectInstance.

Also, another thing that you may consider is making ObjectSpecification
a value, rather than an object. If you look at the table structure you
are trying to achieve, it is pretty much the same as what you get with a
container:

#pragma db value
class ObjectSpecification
{
  int _value;
};


#pragma db object
class ObjectInstance
{
  typedef std::vector<ObjectSpecification> ObjectSpecificationType;

  ObjectSpecificationType _specifications;
};

Here the container's index becomes _idspecification. If you want to
make it lazy-loaded, you can put it in a section (ODB 2.3.0).

Boris



More information about the odb-users mailing list