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" 和获得一对多时的问题的主要内容,如果未能解决你的问题,请参考以下文章