我一直在尝试用hbm文件将以下表映射到Hibernate:
CREATE TABLE
additional_info
(
info_id SMALLINT,
book_id INT,
desc VARCHAR(32) NULL,
CONSTRAINT additional_info_pk PRIMARY KEY (info_id, book_id),
CONSTRAINT additional_info_fk FOREIGN KEY (info_id, book_id) REFERENCES info (id, book_id)
);
CREATE TABLE
info
(
id SMALLINT,
book_id INT,
item_name VARCHAR(32),
CONSTRAINT pk_info PRIMARY KEY (id, book_id ),
CONSTRAINT fk_info FOREIGN KEY (book_id ) REFERENCES book (book_id) );
正如您所看到的,它们都共享相同的两个字段的主键——反过来,这也是一个从additional_info到info的外键。
hibernateTools是这样定义关系的(additional_info hbm):
<composite-id name="id" class="AdditionalInfoId">
<key-many-to-one name="info" class="Info">
<column name="info_id" />
<column name="book_id" />
</key-many-to-one>
</composite-id>
And in info's hbm:
<one-to-one name="additionalInfo" class="AdditionalInfo"></one-to-one>
使用这种方法,我一直得到一个java.lang。stackoverflow 错误。我一直在搜索和尝试不同的映射/替代组合,但没有成功——因为我没有太多的hibernate经验,这更像是胡乱猜测(现在大多数人都在使用注释)。有人建议使用<id>
和<generator>
,但我找不到两个字段被用来连接一对一关系的例子,即PK和FK。我的类都是可序列化的,并且有自动生成的equals和hashCode方法。
我也不明白为什么"key-many-to-one"。这应该是一对一的关系。我读到使用composite-id和这个键-多对一不是一个好主意,但是我没能实现一个可行的替代方案。
如有任何见解,不胜感激。
非常感谢!
PS:一小段堆栈跟踪:
java.lang.StackOverflowError
at java.lang.Integer.equals(Integer.java:747)
at org.hibernate.util.EqualsHelper.equals(EqualsHelper.java:10)
at org.hibernate.type.NullableType.isEqual(NullableType.java:214)
at org.hibernate.type.NullableType.isEqual(NullableType.java:210)
at org.hibernate.type.AbstractType.isEqual(AbstractType.java:116)
at org.hibernate.engine.EntityKey.equals(EntityKey.java:97)
at java.util.HashMap.get(HashMap.java:305)
at org.hibernate.engine.StatefulPersistenceContext.getEntity(StatefulPersistenceContext.java:322)
at org.hibernate.impl.SessionImpl.getEntityUsingInterceptor(SessionImpl.java:478)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromSessionCache(DefaultLoadEventListener.java:436)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:338)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:195)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:846)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:557)
...
如果你定义双向引用,其中一个应该是懒惰的,以避免StackOverflow
。
希望对你有帮助。
看这里:
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html持久化类必须重写equals()和hashCode()来实现复合标识符的相等性。它还必须实现Serializable。
不幸的是,这种方法意味着持久对象是它自己的标识符。除了对象本身之外,没有方便的"句柄"。在加载()与组合键
相关联的持久状态之前,必须实例化持久类本身的实例并填充其标识符属性。希望能有所帮助。