レコードを再利用して相互参照テーブルを作成する際に問題が発生しています。Hibernate は、相互参照テーブルにデータを入力する代わりに、外部キー レコードを更新しようとします。
新しいレコードの挿入は正常に機能します。
DBダイアグラム
新しい場所を追加して相互参照テーブルにリンクすると、問題なく機能します。
//Get specific object
TestContainer tc = (TestContainer) session.createQuery("from TestContainer where id = :id")
.setParameter("id", id).list().get(0);
//Locations
Set<TestContainerLocation> tcl = new HashSet<TestContainerLocation>();
TestContainerLocation loc1 = new TestContainerLocation();
loc1.setLocationName("String1");
TestContainerLocation loc2 = new TestContainerLocation();
loc2.setLocationName("String2");
tcl.add(loc1);
tcl.add(loc2);
tc.setTestContainerLocation(tcl);
session.saveOrUpdate(tc);
既存の場所を再利用しようとすると、うまくいきません。相互参照テーブルに挿入する代わりに、null 値を指定して外部キー テーブルを更新しようとしますが、制約のために失敗します。
//Get specific object
TestContainer tc = (TestContainer) session.createQuery("from TestContainer where id = :id")
.setParameter("id", id).list().get(0);
Set<TestContainerLocation> tcl = new HashSet<TestContainerLocation>();
TestContainerLocation loc1 = new TestContainerLocation();
loc1.setLocationId(1);//existing Id
TestContainerLocation loc2 = new TestContainerLocation();
loc2.setLocationId(2);//existing Id
tcl.add(loc1);
tcl.add(loc2);
tc.setTestContainerLocation(tcl);
session.saveOrUpdate(tc);
エラー:
Hibernate: select testcontai0_.id as id0_, testcontai0_.step_one as step2_0_, testcontai0_.step_two as step3_0_, testcontai0_.step_three as step4_0_, testcontai0_.type_id as type5_0_ from test_container testcontai0_ where testcontai0_.id=?
Hibernate: update test_container_location set location_name=? where location_id=?
Hibernate: update test_container_location set location_name=? where location_id=?
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
...
Caused by: java.sql.BatchUpdateException: Column 'location_name' cannot be null
マッピング
TestContainer.hbm.xml
<class name="TestContainer"
table="test_container">
<id name="id" column="id" type="long" unsaved-value="null">
<generator class="identity"></generator>
</id>
<property name="stepOne" type="string" length="255" column="step_one" not-null="false" />
<property name="stepTwo" type="integer" column="step_two" not-null="false" />
<property name="stepThree" type="string" length="255" column="step_three" not-null="false" />
<many-to-one name="testContainerType" class="org.test.data.TestContainerType" fetch="select">
<column name="type_id" not-null="true"/>
</many-to-one>
<set name="testContainerLocation" table="test_container_location_lookup"
inverse="false" lazy="true" fetch="select" cascade="all">
<key>
<column name="id" not-null="true"/>
</key>
<many-to-many entity-name="org.test.data.TestContainerLocation">
<column name="location_id" not-null="true" />
</many-to-many>
</set>
</class>
TestContainerLocation.hbm.xml
<class name="TestContainerLocation"
table="test_container_location">
<id name="locationId" column="location_id" type="integer" unsaved-value="null">
<generator class="identity"></generator>
</id>
<property name="locationName" type="string" length="255" column="location_name" not-null="false" />
<set name="testContainer" table="test_container_location_lookup"
inverse="true" lazy="true" fetch="select" cascade="all">
<key>
<column name="location_id" not-null="true"/>
</key>
<many-to-many entity-name="org.test.data.TestContainer">
<column name="id" not-null="true" />
</many-to-many>
</set>
</class>