Hibernate inverse=''true" 和获得一对多时的问题

Posted

技术标签:

【中文标题】Hibernate inverse=\'\'true" 和获得一对多时的问题【英文标题】:Hibernate inverse=''true" and problems when getting one-to-manyHibernate inverse=''true" 和获得一对多时的问题 【发布时间】:2011-06-04 13:17:13 【问题描述】:

我正在尝试使用以下映射:

<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>

但当 inverse 设置为 true 时,集合项始终为空。但是,当我将 inverse 设置为 false 时,它​​可以正常工作。 似乎我错过了什么。任何解释都非常感谢。

添加:

抱歉耽搁了,我对代码做了一些更改,但我仍然面临一个问题: 我将包含 3 个项目的类别保存到数据库中,但是当我检索该类别时,它只包含一个项目。这是代码:

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>

提前致谢。

编辑(Stefan Steinegger 根据作者评论)

测试用例:

@Test public void lazyInitTest()
 
  Category cat = new Category(); 
  cat.setName("CTAEGORY_WITH_ITEMS"); 
  Item item = 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()); 

【问题讨论】:

还有其他问题。向我们展示代码。 【参考方案1】:

仅当存在双向关系时才将 inverse 设置为 true。 Inverse 表示由于内存中存在冗余关系,因此不存储该集合。

编辑当然必须映射到同一个数据库字段:

集合转到id

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

并且多对一转到CATEGORY

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

也将设置更改为CATEGORY 以解决问题:

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

【讨论】:

该关联是双向的。我不明白您所说的 ISet 是什么意思?这是java 在内存中应该是双向的。您需要正确设置内存中的关系。如果找不到问题,写个小测试复现一下,贴出代码。 你说得对,Set已经是一个接口了。我从我的答案中删除了它。 @Test public void lazyInitTest() Category cat = new Category(); cat.setName("CTAEGORY_WITH_ITEMS");项目项目 = 新项目(); item.setName("ITEM1");项目 item2 = 新项目(); item2.setName("ITEM2");项目 item3 = 新项目(); item3.setName("测试"); cat.addItem(项目); cat.addItem(item2); cat.addItem(item3); categoryDao.persistCategory(cat);类别类别 = categoryDao.getCategory(cat.getId()); System.out.println(cat.getId() + "--" + category.getId()); Assert.assertEquals(cat.getItems().size(), category.getItems().size()); 评论也不是代码的好地方。我想在这里展示的是测试的行为是相同的——检索到的类别只包含一个项目,因此 las 断言失败。用于检索类别的代码如下所示: public Category getCategoryById(long id) Session session = getSession();事务事务 = session.beginTransaction();交易.开始();类别结果 = (Category) session.get(Category.class, id);事务.commit(); session.close();返回结果; 【参考方案2】:

我怀疑你忘记映射 in Item 但你没有显示映射所以我无法确认。

同样inverse意味着Hibernate不会从这边更新关系信息。确保还设置了 item.setCategory(category) 以正确触发数据库更新。

【讨论】:

你好伊曼纽尔!我已经发布了上面的代码,实际上 Item 是映射的。【参考方案3】:

在您将包含 3 个项目的类别保存到数据库后,您是否检查了所有项目是否正确写入(如连接另一个工具并选择项目,检查 category_id 列)?

如果是:您是否检查了 Hibernate 日志中生成的 SQL 语句?

如果是:这些可以吗?

附注:

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

我一直在到处看到这些。事实上,我从来没有这样做过,只是简单地将项目添加到集合中,其余的由 Hibernate 完成。一直为我工作,我不记得在我的一本 Hibernate 书中看到过其他变体,但现在无法检查。

【讨论】:

是的。我检查了数据库中的记录,项目保存正确 好的,所以持久化数据有效,但对象未正确加载。你能改变你的日志配置来显示hibernate用来加载对象(最好包括绑定变量)并发布结果的sql语句吗?

以上是关于Hibernate inverse=''true" 和获得一对多时的问题的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate中的inverse

hibernate中inverse属性详解

hibernate里的inverse和cascade是什么区别

Hibernate--inverse反转

hibernate inverse属性的作用

Hibernate - lazy, fetch, inverse, cascade