-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Help with Bidirectional OneToMany List using Annotations
PostPosted: Fri Jun 24, 2005 2:37 pm 
Newbie

Joined: Fri Jun 11, 2004 4:58 pm
Posts: 9
I'm having some trouble mapping a bidirectional one to many list using Hibernate 3.0.5, Annotations Beta 2, and hsqldb 1.7.2. Specifically, the index column is null for every new record. What have I done incorrectly?

Code:
@Entity
public class FieldTypeAttribute {
   ...
   @ManyToOne
   @JoinColumn(name="fieldTypeAttribute_id")
   public FieldType getType() {
        return type;
   }

   public void setType(FieldType type) {
        this.type = type;
   }
}

@Entity
public class FieldType extends PersistentEntity {
    ...
    @OneToMany(mappedBy="type", cascade=CascadeType.ALL)
    @IndexColumn(name="typeAttributeIndex")
    public List<FieldTypeAttribute> getAttributes() {
        return attributes;
    }
}



The generated SQL (show_sql=true):
Hibernate: insert into FieldTypeAttribute (name, fieldTypeAttribute_id, description, id) values (?, ?, ?, null)

HSQL Script:
create table FieldType (name varchar(255), description varchar(255), id integer generated by default as identity (start with 1), primary key (id))

create table FieldTypeAttribute (name varchar(255), description varchar(255), id integer generated by default as identity (start with 1), fieldTypeAttribute_id integer, typeAttributeIndex integer, primary key (id))

alter table FieldTypeAttribute add constraint FKDA86EDC8CB49B8FB foreign key (fieldTypeAttribute_id) references FieldType

INSERT INTO FIELDTYPE VALUES('Phone Number',NULL,1)

INSERT INTO FIELDTYPEATTRIBUTE VALUES('Area Code',NULL,1,1,NULL)


Top
 Profile  
 
 Post subject: Workaround
PostPosted: Wed Feb 14, 2007 3:41 pm 
Newbie

Joined: Fri Jan 26, 2007 5:52 am
Posts: 2
I stumbled across this today and found a solution.

It is possible to work around this problem by introducing a position property at the owned side of the association. The getPos() method always computes the position whereas setPos() is empty. You can use mappedBy as usual and an OrderBy annotation on the owner's collection getter. Thus, the position property is stored in the database in a write-only fashion and only used for sorting when the collection is loaded.

Implementation example:
Code:
@Entity
public class Parent {

    private List<Child> children;

    @OneToMany(cascade=CascadeType.ALL, mappedBy = "parent")
    @OrderBy(value = "pos")[
    public List<Child> getChildren() {
        return this.children;
    }

    public void setChildren(List<Child> children) {
        this.children = children;
    }

    int findChildPos(Child c) {
        int result = getChildren().indexOf(c);
        if (result == -1) {
            throw new IllegalStateException("Object hierarchy inconsistent. Child "
              + c + " is not a child of Parent " + this);
        }
        return result;
    }
}

@Entity
public class Child {

    private Parent parent;

    @ManyToOne
    public Parent getParent() {
        return this.parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }

    public Integer getPos() {
        if (this.parent == null) {
            return null;
        }
        return this.parent.findChildPos(this);
    }

    public void setPos(Integer pos) {
        /* empty */
    }

}


Please note that this requires a correct implementation of hashCode() and equals() for the Child class in order for call to List.indexOf(Object) to work. But that should be a basic requirement in any case for persistent classes.

This workaround has proved to work with CascadeType.ALL when the order of the Parent.children list is modified and the Parent is updated. (At least {CascadeType.PERSIST, CascadeType.MERGE} are required for this, otherwise each Child has to be updated manually.)

Of course, this is not ideal as it is intrusive and pollutes domain model classes with technical trick code but it works.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.