Drawback of 'Maintain Bidirectional Relationship'

I recently came to this understanding which changes the way we are trying to use TopLink. I thought I'd share it in an attempt to spare others some of the difficulties we've had, and also to elicit any further clarifications or corrections as necessary.
When you relate two domain objects with TopLink, the Mapping Workbench provides you with the option to Maintain Bidirectional Relationship. What this means is that, for example, if you have two classes Parent and Child, each with a relationship to each other, then all you have to do is call aParent.setChild(aChild) and you will also be able to retrieve the Parent object from the Child with a call to aChild.getParent(), even though you never explicitly called the Child object's setParent(Parent) method. TopLink updates the 'other end' of the relationship for you.
This sounds like a wonderful feature. However, it does have its drawbacks. Let's say that the Child has another Parent, we'll call them ParentOne and ParentTwo. Together, these Parents make up the Child's logical primary key, and so you've mapped these attributes of the Child in TopLink as its primary key attributes. You've also told TopLink to Maintain Birdirectional Relationships between ParentOne.children and Child.parentOne and between ParentTwo.children and Child.parentTwo. Now you've got a particular Child, aChild, owned by Parent instances aParentOne and aParentTwo. You want the Child to be deleted, so you remove it from both of its Parent collections. When you do this, TopLink also removes the references to the Parent objects from aChild, and now you've just altered aChild's primary key. If you selected this Child from the database, TopLink no longer recognizes your instance as the one you selected, and now you're going to have a really hard time deleting it. When you commit your UnitOfWork, you are likely to see an exception that says 'cannot insert null' into one of the LPK fields, or even an OptimisticLockException, as now TopLink is thoroughly confused about what the heck you're doing.
The moral is: Don't use Maintain Bidirectional Relationship on attributes that are part of a class' mapped primary key. And don't set that attribute to null if you want TopLink to continue to recognize the object. In the example above, something like the following would be appropriate:
Child>>
public void orphan(UnitOfWork uow) {
     boolean exists = uow.doesObjectExist(this);
     getParentOne().removeChild(this);
     getParentTwo().removeChild(this);
     if ( exists ) {
          uow.deleteObject(this);
     } else {
          uow.unregisterObject(this);
}Yes, you need to explicitly delete or unregister the object, even if you marked it as Privately Owned by its Parents. The fact that I'm doing the existence check before removing the Child from its Parents is just an extra precaution to make sure I do the test before I do anything that might change the LPK. Although this is probably useless, since, if I do modify the PK, TopLink won't be able to find the object again anyway.

I agree with John's conclusions and will be requesting enhancements to the mapping tools and documentation surrounding b-directional relationships involved in PKs.
One thing I do want to make clear is the original intention of bi-directional relationship support. This was added initially to support EJB 2 relationships. It was also added to the core product for use in some POJO frameworks. It has its uses and does simplify model development but has its trade-offs in addition to what John has posted. It requires indirection in both relationships and the relationship maintenance is only managed when in the context of a TopLink session the objects are read from.
I typically avoid using bi-directional relationship maintenance as the alternative solution of managing the relationships in the model are very straight forward. The result is typically better performing. Additionally, having a POJO model that is not dependent on the persistence manager allows this same model to be used in other contexts such as detachment through serialization.
Also, EJB 3 does not currently have bi-directional relationship management within the specification.
Doug

Similar Messages

  • Maintaining Bidirectional Relationships

    Hi,
    Does someone know exactly what "Maintaining Bidirectional Relationships" means.
    I'm french and I still have some difficulties to understand properly some stuff.
    Then I'd like to understand what it is about.
    Thanks

    Vladislav,
    Bi-directional relationships are ones where two relationships in the model 1:1 or 1:M share the same FK relationship in the database.
    EXAMPLE: An Employee may have a collection of PhoneNumbers and each of those PhoneNumbers has a reference back to its Employee.
    By default developers must write their domain classes so that both sides of the relationship must be set when changing a relationship of this nature.
    When using Bi-directional relationships you would only have to modify one side and the other side would be modified automatically. In the example you would only add a PhoneNumber to an Employee's 1:M collection and the 1:1 back-reference would be automatically set.
    NOTE: Indirection is required on both directions and TransaprentIndirection is required on the 1:M.
    Doug

  • Bidirectional relationships and JPA

    Hi, all!
    Consider the following class containing bidirectional relationship:
    @Entity
    public class Node {
    private Node parent;
    private Collection<Node> childNodes = new HashSet<Node>();
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE})
    public Node getParent() {
    return parent;
    public void setParent(final Node parent) {
    this.parent = parent;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = {CascadeType.ALL})
    public Collection<Node> getChildNodes() {
    return childNodes;
    public void setChildNodes(final Collection<Node> childNodes) {
    this.childNodes = childNodes;
    How should this bidirectional relationship be maintained?
    Should I maintain synchronization between childNodes and parent programmatically like this:
    public void setParent(final Node parent) {
    if ( this.parent != parent ) {
    this.parent = parent;
    parent.addChild(this);
    public void addChild(final Node child) {
    if ( !childNodes.contains(child) ) {
    childNodes.add(child);
    child.setParent(this);
    or can JPA provider (toplink essentials in J2SE environment) do it for me some way (may be some kind of weaving?).
    What is the best practice for this?
    Any help highly appreciated, thanks in advance!

    In JPA you are responsible for maintaining bi-directional relationships in your own code, it is not part of the specification.

  • A problem about bidirectional relationship recovery?

    I have read some snippets of AWT source. A snippet as following:
    ========================================
    * The parent of the object. It may be null for top-level components.
    * @see #getParent
    transient Container parent;
    ========================================
    java.awt.Component and java.awt.Container is a bidirection. But in Component source, the reference to Container is declared as "transient". That means the reference will not been included if the object is serialized. Right?
    If I transmit a Container object with some components to remote machine,how does the remote system recover the bidirectional relationship?

    A serialized Container recovers its "parenthood" by implementing the method void readObject(ObjectInputStream). If you look at the source you will find the lines:
    for(int i = 0; i < ncomponents; i++) {
      component.parent = this;

  • Bidirectional relationship vs IndirectMap

    Our class model have a bidirectional relationship managed by an IndirectMap and a ValueHolder. With TopLink 9.0.3 anything seemed to work well, but with TopLink 9.0.4 we get this error message as soon as we load the project mapping:
    Exception [TOPLINK-179] (OracleAS TopLink - 10g (9.0.4) (Build 031126)): oracle.toplink.exceptions.DescriptorException
    Exception Description: The attribute, [MyAttributeName] uses Bidirectional Relationship Maintenance, but has ContainerPolicy, [MapContainerPolicy(class oracle.toplink.indirection.IndirectMap)] which does not support it. The attribute should be mapped with a different collection type.
    Mapping: oracle.toplink.mappings.OneToManyMapping[MyAttributeName]
    Descriptor: Descriptor(MyClassName --> [DatabaseTable(MyTableName)])
    Is there a way to enable bidirectional relationship with an indirect map?
    Thanks, Yannick

    I'd open a TAR, if it worked in 903 and not 904... 9041 patch was just release on Metalink, Patch "3443153", but I don't see anything in there related to this. Might be worth a shot.
    - Don

  • Maintaining Product relationships in accessories section in product master

    Hi all,
    We have a requirement  to add the maintenance product in the u201CAccessories section in the Relationships tabu201D of the CRM product master data.
    Kindly let me know the standard FM/BAPIu2019s or programs can be used to add the relationship between two products.
    Please note we need the FM/BAPI only to do this.
    With Regards,
    Sujitha.S

    Hi Addy,
    These releationships can be maintained directly in Web UI too. If you have tabs like Accessories under Relationships in Products, then in Web UI too u will see an Assignment Block by name Accessories. If you dont, then pick it from personalisation. If its not in Personalisation then you will have to pick it from Page Configuration.
    But those relationships can be maintained directly in Web UI too but u wont see any Relationships AB in products in Web UI.
    Let me know in case you still have doubts.
    CHeers,
    MG

  • Deleting object having two parents

    Object C is Child of parent A and B.
    Object A and B both contain collection of C and
    C contains one-one mapping with parent A and B.
    If all objects are in memory and I want to delete C
    Then
    If I calls method unitOfWork.deleteObject(c) then
    Whether unitOfWork itself removes object C from its collection in parent object A as well as B
    Or we have to remove object C from collection in parent.
    Please suggest optimized solution to handle the situation.
    Thanks,
    Viral

    I had a similar question a while back:
    Feature Request: Multiple Private Ownersip is ANY or ALL
    I created a 'RequiresOrphaning' interface with an 'orphan' method implemented as follows (which is slightly different from the original version posted in the other thread.)
    public void orphan(UnitOfWork uow) {
      getParentOne().removeChild(this);
      getParentTwo().removeChild(this);
      PersistentDomainObject.orphan(uow, getChildren());
      if (uow.doesObjectExist(this)) {
        uow.deleteObject(this);
      } else {
        uow.unregisterObject(this);
    }The child object needs to be removed from all parents' collections AND explicitly deleted or unregistered. Don't remove the parent from the child's reference, particularly if the parent relationship is part of the child's mapped primary key (see: Drawback of 'Maintain Bidirectional Relationship'
    And if the child has children of its own, the same needs to be done all the way down the tree. PersistentDomainObject is our superclass, and the utility method above for orphaning collections is implemented like this:
    public static void orphan(UnitOfWork uow, Collection aCollection) {
      // We create a new collection because the orphans should try to remove themselves from
      // the collection that the parent is passing us.
      Iterator objectIter = (new ArrayList(aCollection)).iterator();
      while (objectIter.hasNext()) {
        Object object = objectIter.next();
        if (object instanceof RequiresOrphaning) {
          ((RequiresOrphaning)object).orphan(uow);
        } else {
          if ( uow.doesObjectExist(object) ) {
            uow.deleteObject(object);
          } else {
            uow.unregisterObject(object);
    }

  • 1:n relationship back reference?

    Hi! I'm trying to model a 1:n relationship and read in TopLink documentation that, for a 1:n relationship a back poiner 1:1 relation is needed to (from the n-side to the 1-side).
    The documentation sadly does not go into more detail on the back pointer 1:1 relationship, so I'm not sure how I need to model this back-reference. Maybe some of you can shed some light on it:
    1) In the Table Reference tab, do I need to check "Target Foreign Key" for 1:1 back pointer relationship?
    2) Do I need to check "Maintain Bidirectional Relationship"? (If not, how does TL know it is a back pointer?)
    3) Can I use "Private Owned" if the livecycle of the n-side objects is bound to the object on the 1-side?
    4) Will TL take care of filling in the backpointers for objects in that are newly associated (put into the collection on the 1-side)?
    Hint greatly appreciated!
    Sebastian

    Hello Sebastian,
    TopLink recommends a 1:1 backpointer when using a 1:M because of the way the database relation works. A 1:M at the database level is really just a 1:1 relation going the other way. So for an Employee having many phone numbers, at the database level, each phone number has only a single employee.
    Because of that, the Phone table has the foreign key. When you make changes to Employee (say adding new PhoneNumbers), these changes will only cause updates to the Employee table. This in effect makes the 1:M relation very much like a read-only relation. To change the foreign key which is associated to a row in the Phone table, you need a mapping to it in the PhoneNumber object. Best way to do this is a 1:1 mapping, but it doesn't need to be - it can be a direct to field etc if you want to maintain the value yourself.
    1) Since the 1:1 back pointer is just a normal 1:1, it the foreign key is in the source table (Phone). So the mapping should not use the "target foreign key" check box, which is reserved for use if the Target table has the foreign key (ie a back pointer to a 1:1)
    2) "Maintain Bidirectional Relationship" is a concept brought about by ejb2 support. I do not recommend it - It tells TopLink to maintain the relationship rather than leaving control to the application. So when your app sets one side of the relation, the otherside gets set by TopLink after commit. This feature is easily done in code just by having your setter methods set the otherside's relationship. Using this requires both sides to be registered first, and can cause issues when database constraints arent taken into account.
    3) Private ownership is a seperate concept. You would set this on a relationship when the object being refered to should not exist and is dependent on the source object. For instance, Employee might privately own a phone number, but phone number would not own an Employee. This means that removing a PhoneNumber from Employee's collection will cause TopLink to delete it from the database, and that removing employee will cause its PhoneNumbers to also be removed. Only recommended if nothing else can reference the object to be deleted.
    4) No, unless you see #2. I'd really not recommend "Maintain Bidirectional Relationship" as it is really easy to ensure you set both sides of a relationship, and less hassle in the long run.
    Regards,
    Chris

  • Relationship to deleted object not updated?

    Domain: Book <-> BookPageJoin <-> Page
    Book and Page both 'pritavely own' BookPageJoin.
    Both relationships are mapped as 'maintain bidirectional relationship'.
    I start with an instance of each where the Book and Page are joined by an instance of BookPageJoin.
    I delete the Page and commit the UnitOfWork.
    In the database, the Page and BookPageJoin are gone.
    In the UnitOfWork, the Book still has a reference to the BookPageJoin, which still references an instance of the deleted Page.
    This is true even if I call uow.refreshObject(book).
    Shouldn't the BookPageJoin be removed from the UnitOfWork and the Book's collection be updated?
    What did I miss?

    Sorry! Nevermind!
    I just realized that my test code was testing for the presence of a different page than the one I deleted.
    Doh!

  • Many-to-many mapping question

    Hi,
    I'm working with two classes Car and Customer. The Car class has a Vector of Customers and the Customer class has a Vector of Car. Both are related by a many to many mapping.
    I have noticed that I have to set one of the vector to read only to avoid the error message "More than one writable many-to-many mapping can not use the same relation table" in the mapping workbench.
    I can understand that but is there a way to work around, I mean to be able to add a car to a customer and add a customer to a car with the both vectors?
    Is there something to do with the cache?
    I use Vector for the collection or Map class, have I to do otherwise?

    Hello Vladislav, I understand your first question in this thread, but I'm not sure I follow the rest, so let me respond to your first post:
    "I have noticed that I have to set one of the vector to read only to avoid the error message "More than one writable many-to-many mapping can not use the same relation table" in the mapping workbench.
    I can understand that but is there a way to work around, I mean to be able to add a car to a customer and add a customer to a car with the both vectors?"
    The issue here is that with a Many to Many mapping the mapping is responsible for writing to the association table. So, you have a "CAR_CUST" association table. Imagine you add a Car "101" to a customer "501" and the requisite customer "501" to that car "101" in your object model. Then the association table should only be updated once, with an entry of "101, 501". But since the M-M is mapped in both directions, you need to tell TopLink which of these to consider as the "master" when updating the database.
    If you didn't make one of the M-M mappings "read only", then TopLink would insert "101, 501" twice in the association table, and then at a later date you would see that the customer 501 had two 101 cars!
    We do have a feature that allows for TopLink to maintain bidirectional relationships such that if you add or remove a target from one relationship, TopLink will automatically add/remove it from the opposite direction. In my opinion this is lazy programming! A good Java developer should insist on keeping his model up to date on his own. This feature was added because it's part of the EJB spec, not necessarily because it's a good idea ;)
    - Don
    Is there something to do with the cache?
    I use Vector for the collection or Map class, have I to do otherwise?

  • NullPointerException obtained while using multitable with a single class

    Hi,
    I get the following excepting while trying to create a row in database using a class associated with multiple tables in Toplink 10.1.3. I have checked my foreign keys and the tables are not linked through primary keys. Please let me know anything you may know related to this exception.
    Thanks
    [TopLink Warning]: 2005.11.04 03:32:26.453--DatabaseSessionImpl(2161283)--java.lang.NullPointerException
    java.lang.NullPointerException
    at oracle.toplink.internal.descriptors.ObjectBuilder.addPrimaryKeyForNonDefaultTable(ObjectBuilder.java:115)
    at oracle.toplink.internal.descriptors.ObjectBuilder.buildRowForTranslation(ObjectBuilder.java:868)
    at oracle.toplink.queryframework.WriteObjectQuery.prepareForExecution(WriteObjectQuery.java:132)
    at oracle.toplink.queryframework.DatabaseQuery.execute(DatabaseQuery.java:597)
    at oracle.toplink.publicinterface.Session.internalExecuteQuery(Session.java:1994)
    at oracle.toplink.publicinterface.Session.executeQuery(Session.java:977)
    at oracle.toplink.publicinterface.Session.executeQuery(Session.java:934)
    at oracle.toplink.publicinterface.Session.writeObject(Session.java:3073)
    at edu.rit.resapp.toplink.service.ReservationServiceImpl.addTrip(ReservationServiceImpl.java:93)
    at edu.rit.resapp.toplink.service.ReservationServiceImpl.createReservation(ReservationServiceImpl.java:59)
    at edu.rit.resapp.toplink.client.CreateReservation.createRes(CreateReservation.java:46)
    at edu.rit.resapp.toplink.client.CreateReservation.main(CreateReservation.java:22)

    Thanks for the reply. The multiple table descriptor is as follows:
    <descriptor type="relational">
    <name>toplink.model.CustomerImpl</name>
         <class-handle>
    <type-name>toplink.model.CustomerImpl</type-name>
    </class-handle>
         <transactional-policy type="relational">
    <descriptor-alias>CustomerImpl</descriptor-alias>
    <refresh-cache-policy/>
    <caching-policy/>
    <query-manager type="relational"/>
         <locking-policy type="relational">
    <version-locking-column-handle/>
    </locking-policy>
         <primary-key-policy>
         <primary-key-handles>
         <column-handle>
    <column-table-name>CUSTOMER</column-table-name>
    <column-name>CUST_ID</column-name>
    </column-handle>
    </primary-key-handles>
    </primary-key-policy>
    </transactional-policy>
         <mappings>
         <mapping type="direct-to-field">
    <name>cardExpDate</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>cardExpDate</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getCardExpDate()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setCardExpDate(java.util.Date)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>PAYMENT_INFO</column-table-name>
    <column-name>CARD_EXP_DATE</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>cardHolderName</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>cardHolderName</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getCardHolderName()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setCardHolderName(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>PAYMENT_INFO</column-table-name>
    <column-name>CARD_HOLDER_NAME</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>cardNumber</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>cardNumber</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getCardNumber()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setCardNumber(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>PAYMENT_INFO</column-table-name>
    <column-name>CARD_NUMBER</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>cardType</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>cardType</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getCardType()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setCardType(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>PAYMENT_INFO</column-table-name>
    <column-name>CARD_TYPE</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>city</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>city</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getCity()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setCity(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>ADDRESS</column-table-name>
    <column-name>CITY</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>country</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>country</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getCountry()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setCountry(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>ADDRESS</column-table-name>
    <column-name>COUNTRY</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>email</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>email</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getEmail()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setEmail(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>CUSTOMER</column-table-name>
    <column-name>EMAIL</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>firstName</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>firstName</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getFirstName()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setFirstName(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>CUSTOMER</column-table-name>
    <column-name>FNAME</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>id</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>id</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getId()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setId(long)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>CUSTOMER</column-table-name>
    <column-name>CUST_ID</column-name>
    </column-handle>
    </mapping>
         <mapping type="one-to-many">
    <name>invoices</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>invoices</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getInvoices()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setInvoices(java.util.Collection)</method-signature>
    </set-method-handle>
         <reference-descriptor-handle>
    <descriptor-name>toplink.model.InvoiceImpl</descriptor-name>
    </reference-descriptor-handle>
    <maintains-bidirectional-relationship>true</maintains-bidirectional-relationship>
         <relationship-partner-mapping-handle>
    <mapping-descriptor-name>toplink.model.InvoiceImpl</mapping-descriptor-name>
    <mapping-name>customer</mapping-name>
    </relationship-partner-mapping-handle>
         <reference-handle>
    <reference-table-name>INVOICE</reference-table-name>
    <reference-name>INVOICE_CUSTOMER</reference-name>
    </reference-handle>
         <container-policy type="collection">
         <container-class>
    <uses-default-container-class>true</uses-default-container-class>
    </container-class>
    </container-policy>
    </mapping>
         <mapping type="direct-to-field">
    <name>lastName</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>lastName</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getLastName()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setLastName(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>CUSTOMER</column-table-name>
    <column-name>LNAME</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>phone</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>phone</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getPhone()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setPhone(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>CUSTOMER</column-table-name>
    <column-name>PHONE</column-name>
    </column-handle>
    </mapping>
         <mapping type="one-to-many">
    <name>reservations</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>reservations</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getReservations()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setReservations(java.util.Collection)</method-signature>
    </set-method-handle>
         <reference-descriptor-handle>
    <descriptor-name>toplink.model.ReservationImpl</descriptor-name>
    </reference-descriptor-handle>
    <maintains-bidirectional-relationship>true</maintains-bidirectional-relationship>
         <relationship-partner-mapping-handle>
    <mapping-descriptor-name>toplink.model.ReservationImpl</mapping-descriptor-name>
    <mapping-name>customer</mapping-name>
    </relationship-partner-mapping-handle>
         <reference-handle>
    <reference-table-name>RESERVATION</reference-table-name>
    <reference-name>RESERVATION_CUSTOMER</reference-name>
    </reference-handle>
         <container-policy type="collection">
         <container-class>
    <uses-default-container-class>true</uses-default-container-class>
    </container-class>
    </container-policy>
    </mapping>
         <mapping type="direct-to-field">
    <name>state</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>state</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getState()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setState(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>ADDRESS</column-table-name>
    <column-name>STATE</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>streetAddress</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>streetAddress</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getStreetAddress()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setStreetAddress(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>ADDRESS</column-table-name>
    <column-name>STREET</column-name>
    </column-handle>
    </mapping>
         <mapping type="direct-to-field">
    <name>zip</name>
         <attribute-handle>
    <attribute-declaring-type-name>toplink.model.CustomerImpl</attribute-declaring-type-name>
    <attribute-name>zip</attribute-name>
    </attribute-handle>
    <uses-method-accessing>true</uses-method-accessing>
         <get-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>getZip()</method-signature>
    </get-method-handle>
         <set-method-handle>
    <method-declaring-type-name>toplink.model.CustomerImpl</method-declaring-type-name>
    <method-signature>setZip(java.lang.String)</method-signature>
    </set-method-handle>
         <column-handle>
    <column-table-name>ADDRESS</column-table-name>
    <column-name>ZIP</column-name>
    </column-handle>
    </mapping>
    </mappings>
         <primary-table-handle>
    <table-name>CUSTOMER</table-name>
    </primary-table-handle>
    <uses-sequencing>true</uses-sequencing>
    <sequence-number-name>RESAPP_SEQ_CUST</sequence-number-name>
         <sequence-number-table-handle>
    <table-name>CUSTOMER</table-name>
    </sequence-number-table-handle>
         <sequence-number-column-handle>
    <column-table-name>CUSTOMER</column-table-name>
    <column-name>CUST_ID</column-name>
    </sequence-number-column-handle>
         <multi-table-info-policy>
         <secondary-table-holders>
         <table-holder>
         <table-handle>
    <table-name>ADDRESS</table-name>
    </table-handle>
    <primary-keys-have-same-name>false</primary-keys-have-same-name>
         <reference-handle>
    <reference-table-name>CUSTOMER</reference-table-name>
    <reference-name>CUST_ADDR</reference-name>
    </reference-handle>
    </table-holder>
         <table-holder>
         <table-handle>
    <table-name>PAYMENT_INFO</table-name>
    </table-handle>
    <primary-keys-have-same-name>false</primary-keys-have-same-name>
         <reference-handle>
    <reference-table-name>CUSTOMER</reference-table-name>
    <reference-name>CUST_PAY</reference-name>
    </reference-handle>
    </table-holder>
    </secondary-table-holders>
    </multi-table-info-policy>
    </descriptor>
    I have checked and all field seem to be mapped. I also have foreign key constraints set up. Please let me know if anything you feel in the descriptor is incorrect.
    Thanks.

  • FK problem when inserting one-to-many records

    Hi everybody,
    I see that this subject has been discussed here from time to time before, as in:
    insert record with 1-M mapping missing foreign key using UOW
    Sequences and multiple tables for inheritance
    I followed Dougs advice on several posts, to check out the employee exampled shipped with Toplink, but regardless of all this information, I'm still stuck.
    So, my issue: when I create new objects, add them to some other objects collection, and then call "assign sequence numbers" on all of them, the sequencenumbers are assgned all the way down the hierachy, but the upward links - the foreign keys - are not updated with the ID's of the parent object.
    Simple example (might not compile - demo code):
    <JAVA>
    myInputController.session = (DatabaseSession)
    SessionManager.getManager().getSession("some_session");
    UnitOfWork myUnitOfWork = myInputController.session.acquireUnitOfWork();
    // Father and Child are a Toplink objects, persisted to each their table with a
    // FK relation, is now assigned to the UOW
    Father myDBFather = (Father) myUnitOfWork.registerObject(new Father());
    Child myDBChild = new Child();
    myDBFather.getChildCollection().add(myDBChild);
    // Now I could use the accessor methods of the Toplink objects to set
    // stuff like name, phone number or so, but that's not important for demo.
    // I just want to save my objects to the database. To do so, I need to
    // assign sequence numbers:
    myUnitOfWork.assignSequenceNumbers();
    // I check the ID's before writing to DB:
    System.out.println(myDBFather.GetId().toString());
    System.out.println(myDBChild.GetId().toString());
    // They both return valid numbers, similar to what the sequence objects
    // of the database should asssign, so that works.
    // But:
    System.out.println(myDBChild.GetFaterid().toString());
    // Will return null, even if myDBChild is a child of myDBFather, and
    // hence a commit to the database will fail (no foreign key!).
    // I can fix this, by "manually" setting the id:
    myDBChild.SetFatherid(myDBFather.getId());
    // And then a commit to the database will work:
    myUnitOfWork.commit();
    // But, since I have deep hierachies, and don't allways know what
    // objects have been added/changed, it's a pretty wild thing, not
    // to menition un-ellegant and heavy in maintenance, to loop down
    // through the entire collection and update all foreign key ID's
    // (FatherID's) before committing changes.
    </JAVA>
    I guess I'm just not hitting the right button somewhere? To create the Toplink Java classes and descriptors, I used "Java objects from tables" in JDev 10.1.2, both "as is", and with some tinkering on indirection, transparency and bi-directional relationships. Also, I get same results in the Toplink 10.1.3 dp4.
    I must have missed the answer somewhere out there, but must post after trying really hard!
    Best regards to all of you,
    :) Ulf

    I could kick myself right now!
    The child setFatherid method takes an entire father object, so the code must be myDBChild.SetFatherid(myDBFather); instead of the myDBChild.SetFatherid(myDBFather.getId()); My apologies.
    With the issue still very present, I post some code from the auto-generated child-class and the child-class descriptor below, which might give some pointers.
    <JAVA-FRAGMENT>
    package dk.test.fatherchild.model;
    import oracle.toplink.indirection.ValueHolder;
    import oracle.toplink.indirection.ValueHolderInterface;
    public class Child {
    * Map fatherid <-> dk.test.fatherchild.model.Father
    * @associates <{dk.test.fatherchild.model.Father}>
         private ValueHolderInterface fatherid;
         private Double childid;
         private String childName;
    public Child() {
         super();
         this.fatherid = new ValueHolder();
    </JAVA-FRAGMENT>
    <Child.ClassDescriptor.xml-FRAGMENT>
    <mapping>
    <inherited>false</inherited>
    <instance-variable-name>fatherid</instance-variable-name>
    <uses-method-accessing>false</uses-method-accessing>
    <read-only>false</read-only>
    <get-method-handle>
    <method-handle empty-aggregate="true"/>
    </get-method-handle>
    <set-method-handle>
    <method-handle empty-aggregate="true"/>
    </set-method-handle>
    <reference-descriptor>dk.test.fatherchild.model.Father.ClassDescriptor</reference-descriptor>
    <private-owned>false</private-owned>
    <uses-batch-reading>false</uses-batch-reading>
    <maintains-bidirectional-relationship>true</maintains-bidirectional-relationship>
    <relationship-partner-mapping-name>childCollection</relationship-partner-mapping-name>
    <table-reference-mapping-reference-handle>
    <reference-handle>
    <reference-table>PERIODICA2.CHILD</reference-table>
    <reference-name>CHILD_FATHER_FK</reference-name>
    </reference-handle>
    </table-reference-mapping-reference-handle>
    <uses-joining>false</uses-joining>
    <one-to-one-mapping-indirection-policy>
    <indirection-policy>
    <uses-indirection>true</uses-indirection>
    </indirection-policy>
    </one-to-one-mapping-indirection-policy>
    <mapping-class>MWOneToOneMapping</mapping-class>
    </mapping>
    </Child.ClassDescriptor.xml-FRAGMENT>

  • How to create a one to one bidirectional mapping

    Hi,
    I'm trying to create a one to one bidirectional mapping. To simplify, I tried to modify the TwoTierEmployee sample in order to turn the one to one mapping between Employee and Address into a bidirectional one.
    First I have added a new attribute ("employee") to the Address descriptor and I mapped it in a one to one relationship with the "address" attribute of the Employee descriptor, by using the same EMPLOYEE_ADDRESS foreign key as a target one (checked "Target Foreign Key"). Afterwards, in the Employee descriptor I checked the address attribute "Maintain Bidirectional Relanship" check box and I selected "employee" in the "Relationship Partner" combo box. At that moment I got the following TopLink error message (sorry, that's in french):
    "Le mapping de partenaires indiqué ne désigne pas ce mapping comme étant son propre partnenaire"
    meaning something like:
    "The partner's mapping doesn't indicate this mapping as being its own partner"
    Since I didn't find any sample of bidirectional one to one relationship neither in the documentation nore in tutorials, any help would be highly apreciated.
    Many thanks in advance,
    Nicolas

    Hi Nicolas,
    The intent behind this particular error message is that for a bidirectional mapping, there need to be two equal partner mappings. It looks like in this case that you intend the Address.employee mapping to be paired with the Employee.address mapping. It could be simply that you haven't selected the Address.employee mapping's relationship partner (Employee.address). But if you have chosen the partner mapping on both mappings, and it still gives you the error message, then it looks to be incorrect behavior. If that is the case, if you could provide us with your version information, we can make sure that that issue is recorded.

  • Problem with 1-to-many relationship between entity beans

    Hi All!
    I have two tables TMP_GROUP and TMP_EMPLOYEE with following fields:
    TMP_GROUP: ID, CAPTION, COMMENT, STATUS.
    TMP_EMPLOYEE: ID, LOGIN, GROUP_ID.
    For this tables i create two entity beans GROUP and EMPLOYEE respectively.
    The relationship looks like this
    descriptor ejb.xml:
    <ejb-relation>
                <description>description</description>
                <ejb-relation-name>employeesOfGroup</ejb-relation-name>
                <ejb-relationship-role>
                    <ejb-relationship-role-name>com.mypackage.GroupBean</ejb-relationship-role-name>
                    <multiplicity>One</multiplicity>
                    <relationship-role-source>
                        <ejb-name>GroupBean</ejb-name>
                    </relationship-role-source>
                    <cmr-field>
                        <cmr-field-name>employees</cmr-field-name>
                        <cmr-field-type>java.util.Collection</cmr-field-type>
                    </cmr-field>
                </ejb-relationship-role>
                <ejb-relationship-role>
                    <ejb-relationship-role-name>com.mypackage.EmployeeBean</ejb-relationship-role-name>
                    <multiplicity>Many</multiplicity>
                    <relationship-role-source>
                        <ejb-name>EmployeeBean</ejb-name>
                    </relationship-role-source>
                </ejb-relationship-role>
            </ejb-relation>
    descriptor persistent.xml:
    <table-relation>
                   <table-relationship-role
                        key-type="PrimaryKey">
                        <ejb-name>GroupBean</ejb-name>
                        <cmr-field>employees</cmr-field>
                   </table-relationship-role>
                   <table-relationship-role
                        key-type="NoKey">
                        <ejb-name>EmployeeBean</ejb-name>
                        <fk-column>
                             <column-name>GROUP_ID</column-name>
                             <pk-field-name>ejb_pk</pk-field-name>
                        </fk-column>
                   </table-relationship-role>
              </table-relation>
    Now i implement business method:
    public Long addEmployee(String login, long groupId) {
              Long result;
              try {
                   EmployeeLocal employee = employeeHome.create(login);
                   GroupLocal group =
                        groupHome.findByPrimaryKey(new Long(groupId));
                   Collection employees = group.getEmployees();
                   employees.add(employee);
                   result = (Long) employee.getPrimaryKey();
              } catch (CreateException ex) {
                   result = new Long(0);
              } catch (FinderException ex) {
                   result = new Long(0);
              return result;
    When i call this method from web service, the following exception is raised:
    com.sap.engine.services.ejb.exceptions.BaseTransactionRolledbackLocalException: Exception in method com.mypackage.GroupLocalHomeImpl0.findByPrimaryKey(java.lang.Object).
    P.S.
    1) I have transaction attribute set to "Required" for all methods of all beans
    2) I have unique index for each table:
    TMP_GROUP_I1: CAPTION
    TMP_EMPLOYEE_I1: LOGIN (however i think GROUP_ID must be added here too)
    3) I tried many:many relationship with this tables and it works fine
    4) I try another implementation of addEmployee method with
    EmployeeLocal employee = employeeHome.create(login, groupId);
    without using GroupLocal cmr-field and GroupLocalHome findByPrimaryKey method, the result is same error.
    Can somebody help me with this problem?
    Thanks in advance.
    Best regards, Abramov Andrey.

    gimbal2 wrote:
    1: The @JoinColumn on the listOfDepartments collection in Company is wrong. It should be something like this for a bidirectional relationship:
    @OneToMany(mappedBy="company") // company is the matching property name in Department
    private List <Department> listOfDepartment = new ArrayList<Department>();Note that I removed the fetch configuration; onetomany is fetched lazy by design. Saves some clutter eh.
    2: use a Set in stead of a List (hibernate doesn't like lists much in entities and will break when you create slightly more complex entity relations)
    3: don't just slap cascades on collections, especially of type ALL. Do it with care. In the many years I've been using JPA I've only had to cascade deletes in very specific situations, maybe once or twice. I never needed any of the other cascade types, they just invite sloppy code if you ask me. When working with persistence you should apply a little precision.I made all changes as you mentioned but still compID in department table shows null value...

  • Can anyone tried register relationship in ECC 6.0

    Hello isuians,
    In ecc 6.0 , the standard no. range object  "isu_indexn" is missed .this no. range is used to maintain register relationship.
    i know that the same no. range object exist in 4.72 but not there in ECC 6.0
    The issue is isu_indexn is standard no. range object  ,does it require any enhancements for to include in ecc 6.0
    or if anyone working in ECC 6.0 PLEASE REPLI BACK with whether it is there in thier 6.0 systems.

    Hi ,
    AS SUGGESTED BY SAP:
    Manually create this number range object as follows:
    Start transaction SNUM, and create the ISU_INDEXN object
    Object name               ISU_INDEXN
    Short text                Indexnr_ZwBeziehung
    Long text                Indexnumber of register relationship
    To-year flag
    Number length domain      INDEXNR
    No interval rolling
    Number range transaction
    Warning %                 1,0
    Main memory buffering
    No of numbers in buffer   10
    The object is part of package EE07.
    OR
    Import the relevant Add-on Support Package
    Support Packages:  SAPK-60007INISUT
    Deepak.

Maybe you are looking for

  • How to put header and how to insert logo in this report

    HI I want  a header and logo in this report.how to do this in ALV report.Also why we have to put the          sy-repid.Plz tell me in this report where i have to do all this.Plz show me in detail. REPORT  ZREPORT_ALV . TYPE-POOLS : slis. tables:vbak,

  • Essbase Data Export not Overwriting existing data file

    We have an ODI interface in our environment which is used to export the data from Essbase apps to text files using Data export calc scripts and then we load those text files in a relational database. Laetely we are seeing some issue where the Data Ex

  • Search results appear in red and/or crossed out

    Hi! Has anyone seen this before, or is anyone able to reproduce it? http://homepage.mac.com/thomas.leaute/Safarirenderingerrors.gif (I also posted this on the Safari forum, but then I just realized that I can reproduce it with Firefox, so this is a w

  • Tutorial: Azure AD Integration with Bluejeans

    Click reply and tell us what you think: Tutorial: Azure AD Integration with Bluejeans Markus Vilcinskas, Knowledge Engineer, Microsoft Corporation

  • Net Browser and Form 6i and Report 6i

    Is there any one who can help me how to config the Form server and report server in Developer 6i. I had tried much and much but useless. so please send some material that use full for configration of Form Server and Report Server