开发者

Hibernate inverse=''true" and problems when getting one-to-many

I am trying to use the following mapping :

<class name="Category" table="CATEGORY" lazy="false">
    <id name="id" type="java.lang.Long" >
        <column name="ID" />
        <generator class="native" />
    </id>

    <property name="name" type="java.lang.String"/>

    <set name="items" inverse="true" lazy="false" access="field" cascade="all">
        <key column="id" not-null="true"></key>
        <one-to-many  class="Item" />
    </set>

</class>

But when inverse is set to true, set of items is always empty. However, when I set inverse to false it works fine. Seems that I have missed something. Any explanations are highly appreciated.

ADDED:

Sorry for delay, I've made few changes to the code, but I am still facing a problem: I am saving category with 3 items to the database, but when I retrieve that category back, it contains only one item. Here is the code:

public class Category {

    private long id;

    private int version;

    private String name;

    private Set<Item> items;

    public Category() {
        this.items = new HashSet<Item>();
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void addItem(Item item) {
        this.items.add(item);
        item.setCategory(this);
    }

    public Set<Item> getItems() {
        return items;
    }

}



   <hibernate-mapping >
        <class name="Category" table="HIA_CATEGORY" lazy="false">
            <id name="id" type="java.lang.Long" >
                <column name="ID" />
                <generator class="native" />
            </id>
            <version name="version" column="VERSION" ></version>

            <property name="name" type="java.lang.String"/>

            <set name="items" inverse="true" lazy="false" access="field" cascade="all" outer-join="false">
                <key column="id" not-null="true"></key>
                <one-to-many  class="Item"  />
            </set>

        </class>
    </hibernate-mapping>

public class Item {

    protected long id;

    protected String name;

    protected Category category;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
        category.getItems().add(this);
    }

}


<hibernate-mapping>
    <class name="Item" table="HIA_ITEM" lazy="false" 
        abstract="false" polymorphism="implicit">
        <id name="id" type="java.lang.Long">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String" />


        <many-to-one name="category" update="true" cascade="save-update" access="field" lazy="false" outer-join="false"
            class="Category" column="CATEGORY">
        </many-to-one>
        <joined-subclass name="ExtItem" 
            table="EXT_ITEM" >
            <key column="id"></key>
            <property name="extProperty" column="EXT_PROPERTY"></property>
        </joined-subclass>
    </class>
</hibernate-mapping>

Thanks in advance.

Edit (by Stefan Steinegger according to comment by author)

Test case:

@Test public void lazyInitTest()
{ 
  Category cat = new Category(); 
  cat.setName("CTAEGORY_WITH_ITEMS"); 
  Item item = 开发者_StackOverflow中文版new Item(); 
  item.setName("ITEM1"); 
  Item item2 = new Item(); 
  item2.setName("ITEM2"); 
  Item item3 = new Item(); 
  item3.setName("Test"); 
  cat.addItem(item); 
  cat.addItem(item2); 
  cat.addItem(item3); 

  categoryDao.persistCategory(cat);

  Category category = categoryDao.getCategory(cat.getId()); 

  System.out.println(cat.getId() + "--" + category.getId());

  Assert.assertEquals(cat.getItems().size(), category.getItems().size()); 
}


Only set inverse to true if there is a bidirectional relation. Inverse means that the set isn't stored because there is a redundant relation in memory.

Edit And of course it must be mapped into the same database field:

The set goes to id:

<set name="items" ...>
    <key column="id" not-null="true"/>
    <one-to-many  class="Item"  />
</set>

and the many-to-one goes to CATEGORY:

<many-to-one ... column="CATEGORY">
</many-to-one>

Change the set to CATEGORY as well to fix the problem:

<set ...>
    <key column="CATEGORY" not-null="true"/>
    <one-to-many  class="Item"  />
</set>


I suspect you have forgotten to map the in Item but you're not showing the mapping so I can't confirm.

Also inverse means that Hibernate won't update the relationship information from this side. Make sure to also have item.setCategory(category) setup to properly trigger the database update.


After you saved the Category with it's 3 Items to the database, did you check if all the Items were written correctly (as in connected with another tool and selected the Items, checking the category_id column)?

If yes: Did you check the Hibernate-Logs for the SQL-Statements generated?

If yes: Were these ok?

As a side note:

public void setCategory(Category category) {
    this.category = category;
    category.getItems().add(this);
}

I keep seeing these all over the place. In fact I never did this but simply added the items to the collection and did Hibernate do the rest. Always worked for me and I can't remember seeing the other variant in one of my Hibernate books but can't check right now.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜