A developer here is working on a program that has an entity containing a List of children. He defined the relationship with this mapping:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="com.plumcreek.ngts.accrual.Accrual" table="ACCRUAL">
<id column="ACCRUALID" name="accrualId" type="java.lang.Long">
<generator class="native" />
</id>
<version column="UPDATECOUNT" name="updateCount" />
<property column="district" length="5" name="district" not-null="true" type="java.lang.String" />
<property column="entryUser" length="15" name="entryUser" not-null="true" type="java.lang.String" />
<property column="approvalUser" length="15" name="approvalUser" type="java.lang.String" />
<property column="companyId" name="companyId" not-null="true" type="java.lang.Integer" />
<property column="office" length="5" name="office" not-null="true" type="java.lang.String" />
<property column="acquisitionType" length="5" name="acquisitionType" not-null="true" type="java.lang.String" />
<property column="accountingPeriod" length="7" name="accountingPeriod" not-null="true" type="java.lang.String" />
<property column="vendorType" length="5" name="vendorType" not-null="true" type="java.lang.String" />
<property column="loggingMethod" length="5" name="loggingMethod" not-null="true" type="java.lang.String" />
<property column="destinationType" length="3" name="destinationType" not-null="true" type="java.lang.String" />
<property column="expenseOffset" length="6" name="expenseOffset" type="java.lang.String" />
<property column="revenueOffset" length="6" name="revenueOffset" type="java.lang.String" />
<property column="customer" length="14" name="customer" type="java.lang.String" />
<property column="destination" length="5" name="destination" type="java.lang.String" />
<property column="state" length="3" name="state" type="java.lang.String" />
<property column="toe" length="5" name="toe" type="java.lang.String" />
<property column="depletionPoolId" name="depletionPool" type="java.lang.Integer" />
<property column="depletionTypeId" name="depletionType" type="java.lang.Integer" />
<property column="accrualType" name="accrualType" not-null="true" type="java.lang.Integer" />
<property column="status" length="3" name="status" not-null="true" type="java.lang.String" />
<property column="postingDate" name="postingDate" type="java.util.Date" />
<property column="adjustmentComment" length="20" name="adjustmentComment" type="java.lang.String" />
<property column="glComment" length="20" name="glComment" type="java.lang.String" />
<property column="updateUser" length="15" name="updateUser" type="java.lang.String" />
<property column="updateDate" name="updateDate" type="java.util.Date" />
<property column="insertUser" length="15" name="insertUser" not-null="true" type="java.lang.String" />
<property column="insertDate" name="insertDate" not-null="true" type="java.util.Date" />
<list name="accrualDetailList" inverse="true" cascade="all-delete-orphan">
<key column="accrualId" />
<index column="sequence" />
<one-to-many class="com.plumcreek.ngts.accrual.AccrualDetail" />
</list>
</class>
<class name="com.plumcreek.ngts.accrual.AccrualDetail" table="ACCRUALDETAIL">
<id column="ACCRUALDETAILID" name="accrualDetailId" type="java.lang.Long">
<generator class="native" />
</id>
<version column="UPDATECOUNT" name="updateCount" />
<property column="sequence" name="sequence" type="java.lang.Long" not-null="true" />
<property column="accrualId" name="accrualId" type="java.lang.Long" />
<property column="account" name="account" type="java.lang.String" length="6" />
<property column="majorProduct" name="majorProduct" type="java.lang.String" length="6" />
<property column="accrualAmount" name="amount" type="java.lang.Double" />
<property column="volume1" name="volume1" type="java.lang.Double" />
<property column="volume2" name="volume2" type="java.lang.Double" />
<property column="unitOfMeasure1" name="uom1" type="java.lang.String" length="5" not-null="true" />
<property column="unitOfMeasure2" name="uom2" type="java.lang.String" length="5" />
<property column="accrualCategory" name="category" type="java.lang.String" length="10" not-null="true"/>
<property column="bookOrTax" name="bookOrTax" type="java.lang.String" length="1" not-null="true" />
<property column="updateUser" name="updateUser" type="java.lang.String" length="15" />
<property column="updateDate" name="updateDate" type="java.util.Date" />
<property column="insertUser" name="insertUser" type="java.lang.String" length="15" not-null="true" />
<property column="insertDate" name="insertDate" type="java.util.Date" not-null="true" />
</class>
</hibernate-mapping>
For some reason on an insert it is running a delete orphans, which I think is the root of the problem. In debug, I can see that the He does a session.add(object) it looks for orphans fails with a null pointer exception because ce is null in this code:
public Collection getOrphans(PersistentCollection coll) throws HibernateException {
CollectionEntry ce = getCollectionEntry(coll);
return ce.isNew() ? EMPTY : coll.getOrphans( ce.getSnapshot() );
}
Does this seem like a bug or is he trying to do something that isn't supported? If it is a bug, would it hurt to add a check to see if ce is null before running the is new?
This stack trace shows where it retrieves ce but the code indicates that a null can be returned.
Thread [main] (Suspended)
HashMap.get(Object) line: 322 [local variables unavailable]
SequencedHashMap.get(Object) line: not available [local variables unavailable]
IdentityMap.get(Object) line: 126
SessionImpl.getCollectionEntry(PersistentCollection) line: 692
SessionImpl.getOrphans(PersistentCollection) line: 3120
Cascades.deleteOrphans(PersistentCollection, SessionImplementor) line: 542
Cascades.cascadeCollection(Cascades$CascadingAction, Cascades$CascadeStyle, PersistentCollectionType, Type, Object, int, SessionImplementor, Object) line: 533
Cascades.cascade(SessionImplementor, Object, Type, Cascades$CascadingAction, Cascades$CascadeStyle, int, Object) line: 452
Cascades.cascade(SessionImplementor, ClassPersister, Object, Cascades$CascadingAction, int, Object) line: 503
SessionImpl.doSave(Object, Key, ClassPersister, boolean, boolean, Cascades$CascadingAction, Object) line: 893
SessionImpl.doSave(Object, Serializable, ClassPersister, boolean, Cascades$CascadingAction, Object) line: 818
SessionImpl.saveWithGeneratedIdentifier(Object, Cascades$CascadingAction, Object) line: 738
SessionImpl.save(Object) line: 718
HibernateDaoImpl.add(Object, Session) line: 104
HibernateDaoImpl.add(Object) line: 84
AccrualService(AbstractDaoService).add(Object) line: 22
AccrualService.writeRelatedAccrualRecords(Accrual) line: 144
AccrualService.save(Accrual) line: 83
AccrualServiceTest.testAdjustmentWithDepletion() line: 152
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 [local variables unavailable]
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 [local variables unavailable]
Method.invoke(Object, Object[]) line: 324 [local variables unavailable]
AccrualServiceTest(TestCase).runTest() line: 154
AccrualServiceTest(TestCase).runBare() line: 127
TestResult$1.protect() line: 106
TestResult.runProtected(Test, Protectable) line: 124
TestResult.run(TestCase) line: 109
AccrualServiceTest(TestCase).run(TestResult) line: 118
TestSuite.runTest(Test, TestResult) line: 208
TestSuite.run(TestResult) line: 203
TestRunner.doRun(Test, boolean) line: 116
TestRunner.doRun(Test) line: 109
TestRunner.run(Test) line: 72
TestRunner.run(Class) line: 57
AccrualServiceTest.main(String[]) line: 32
|