2

我正在使用 postgreql(如果有的话)并且我有两个具有此映射的类:

<hibernate-mapping>
<class name="com.mydomain.models.TokenizedForm" table="TOKENIZEDFORM">
 <id name="id" type="java.lang.Integer">
  <column name="ID" sql-type="INTEGER"/>
  <generator class="increment"/>
 </id>
 <property generated="never" lazy="false" name="name" type="java.lang.String">
  <column length="255" name="NAME" sql-type="VARCHAR"/>
 </property>
 <property generated="never" lazy="false" name="body" type="java.lang.String">
  <column length="9999999" name="BODY" sql-type="VARCHAR"/>
 </property>
 <set lazy="true" name="tokens" sort="unsorted" table="FORMTOKENS">
  <key>
   <column name="ID" sql-type="INTEGER"/>
  </key>
  <one-to-many class="com.mydomain.models.FormTokens"/>
 </set>
</class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                                   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Oct 7, 2013 10:31:46 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
 <class name="com.mydomain.models.FormTokens" table="FORMTOKENS">
  <id name="id" type="java.lang.Integer">
   <column name="ID" sql-type="INTEGER"/>
   <generator class="increment"/>
  </id>
  <property generated="never" lazy="false" name="text" type="java.lang.String">
   <column length="1023" name="TEXT" sql-type="VARCHAR"/>
  </property>
  <property generated="never" lazy="false" name="delimiter" type="java.lang.String">
   <column length="255" name="DELIMITER" sql-type="VARCHAR"/>
  </property>
  <many-to-one class="com.mydomain.models.TokenizedForm"
   fetch="join" name="form">
   <column name="FORM" sql-type="INTEGER"/>
  </many-to-one>
 </class>
</hibernate-mapping>

现在运行此代码时:

Session session = getSession();
Transaction transaction = session.getTransaction();
transaction.begin();

TokenizedForm form = new TokenizedForm("my fm", "body of it here");
session.save(form);

FormTokens ft0 = new FormTokens("my token 1", "[[]]");
ft0.setForm(form);

FormTokens ft1 = new FormTokens("my t1", "<<>>");
ft1.setForm(form);

session.save(ft0);
session.save(ft1);

transaction.commit();

我得到以下信息:

Hello World!
log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select max(ID) from TOKENIZEDFORM
Hibernate: select max(ID) from FORMTOKENS
Hibernate: insert into TOKENIZEDFORM (NAME, BODY, ID) values (?, ?, ?)
Hibernate: insert into FORMTOKENS (TEXT, DELIMITER, FORM, ID) values (?, ?, ?, ?)
Hibernate: insert into FORMTOKENS (TEXT, DELIMITER, FORM, ID) values (?, ?, ?, ?)
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement
  at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)
  at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
  at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
  at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
  at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:136)
  at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:58)
  at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3067)
  at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3509)
  at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
  at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377)
  at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:369)
  at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:286)
  at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:339)
  at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
  at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
  at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
  at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
  at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
  at com.mydomain.App.d(App.java:55)
  at com.mydomain.App.main(App.java:22)
Caused by: org.postgresql.util.PSQLException: ERROR: insert or update on table "formtokens" violates foreign key constraint "fk_37kmr0diunms0vx0boagmc43f"
  Detail: Key (id)=(3) is not present in table "tokenizedform".
  at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:334)
  at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:133)
  ... 15 more

其中 3 是 FormToken 的 ID。不是数据库中的 TokenizedForm。(tf0 和 tf1 id 是 2 和 3,因为我已经将 ID 为 1 的行插入到数据库中)。
如果我尝试只添加一个 FormToken它在每次运行中都有效!在一次运行期间添加的两个或多个 FormToken 实例会出现此问题。我可以通过在每次运行期间仅添加一个 FormTokens 实例来添加数十亿个 FormTokens。
我尝试从 TokenizedForm 中删除 FormTokens 的任何痕迹,但是(从映射中删除集合和...)但没有任何区别,我什至尝试在插入一个 FormToken 后提交并开始新事务。我也尝试关闭和打开一个新会话!但同样的事情一遍又一遍地发生。
我究竟做错了什么?

4

1 回答 1

1

请参阅文档以了解如何映射双向一对多关联。您的映射是错误的,因为它告诉

<set lazy="true" name="tokens" sort="unsorted" table="FORMTOKENS">
  <key>
   <column name="ID" sql-type="INTEGER"/>
  </key>
  <one-to-many class="com.mydomain.models.FormTokens"/>
</set>

formtokens 中的 ID 列用于引用 tokenizedforms 表的主键。它应该是

<set lazy="true" name="tokens" sort="unsorted" table="FORMTOKENS">
  <key>
   <column name="FORM" sql-type="INTEGER"/>
  </key>
  <one-to-many class="com.mydomain.models.FormTokens"/>
</set>

反而。当然,请确保从头开始重新生成数据库模式,让 Hibernate 为您生成它,因为它可能生成了一个 FK 约束,当您尝试完全删除该集合时该约束没有被删除。

于 2013-10-07T20:20:16.650 回答