Нарушение ограничения ссылочной целостности с помощью datanucleus и двунаправленного 1-N в блокировке optimisti c при использовании типа интерфейса - PullRequest
1 голос
/ 07 февраля 2020

У нас есть 1-N двунаправленных отношений с зависимыми элементами, и где отображаемое поле имеет тип интерфейса. Доступ к тестовому сценарию, воспроизводящему проблему, можно получить здесь https://github.com/didierschlegel/test-jdo (это ответвление проекта jdo-test от datanucleus).

public interface IInventory {
    /**
     * @return the products in this inventory
     */
    Set<Product> getProducts(); 
}
@PersistenceCapable
public class Inventory implements IInventory
{
    @PrimaryKey
    protected String name=null;

    @Persistent(mappedBy="inventory")
    @Join
    @Element(dependent="true")
    protected Set<Product> products = new HashSet<Product>();

    ...
}
@PersistenceCapable
public class Product
{
    @PrimaryKey
    @Persistent(valueStrategy=IdGeneratorStrategy.NATIVE)
    protected long id;

    @Persistent(types=Inventory.class)
    protected IInventory inventory=null;

    ...
}
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

    <!-- Tutorial "unit" -->
    <persistence-unit name="MyTest">
        <class>mydomain.model.Inventory</class>
        <class>mydomain.model.Product</class>
        <exclude-unlisted-classes/>
        <properties>
            <property name="datanucleus.schema.autoCreateAll" value="true"/>
            <property name="javax.jdo.option.Optimistic" value="true"/>
            <!-- ENABLE THESE FOR H2 -->
            <property name="javax.jdo.option.ConnectionURL" value="jdbc:h2:mem:nucleus1"/>
            <property name="javax.jdo.option.ConnectionUserName" value="sa"/>
            <property name="javax.jdo.option.ConnectionPassword" value=""/>
        </properties>
    </persistence-unit>
</persistence>
public class SimpleTest {
    @Test
    public void testSimple() {
        NucleusLogger.GENERAL.info(">> test START");
        PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("MyTest");
        PersistenceManager pm = pmf.getPersistenceManager();
        Transaction tx = pm.currentTransaction();
        try {
            tx.begin();
            Inventory inv = new Inventory("My Inventory");
            Product product = new Product("Sony Discman", "A standard discman from Sony", 200.00, inv);
            Product book = new Product("Lord of the Rings by Tolkien", "The classic story", 49.99, inv);
            inv.getProducts().add(product);
            inv.getProducts().add(book);
            pm.makePersistent(inv);
            tx.commit();
            Object inventoryId = pm.getObjectId(inv);
            assertNotNull(inventoryId);
            pm.close();

            pm = pmf.getPersistenceManager();
            tx = pm.currentTransaction();
            tx.begin();
            Query<Inventory> qi = pm.newQuery(Inventory.class);
            assertEquals(1, qi.executeList().size());
            Query<Product> qp = pm.newQuery(Product.class);
            assertEquals(2, qp.executeList().size());
            tx.commit();
            pm.close();

            pm = pmf.getPersistenceManager();
            tx = pm.currentTransaction();
            tx.begin();
            pm.deletePersistent(pm.getObjectById(inventoryId));
            tx.commit();
            pm.close();

            pm = pmf.getPersistenceManager();
            tx = pm.currentTransaction();
            tx.begin();
            qi = pm.newQuery(Inventory.class);
            assertEquals(0, qi.executeList().size());
            qp = pm.newQuery(Product.class);
            assertEquals(0, qp.executeList().size());
            tx.commit();
        } catch (Throwable thr) {
            NucleusLogger.GENERAL.error(">> Exception in test", thr);
            fail("Failed test : " + thr.getMessage());
        } finally {
            if (tx.isActive()) {
                tx.rollback();
            }
            pm.close();
        }

        pmf.close();
        NucleusLogger.GENERAL.info(">> test END");
    }
}

Тестовый пример успешно выполняется с параметром "javax.jdo.option.Optimisti c", установленным в значение "false", но при изменении его на "true" выдается следующее исключение:

18:31:45,057 (main) WARN  [DataNucleus.Datastore.Persist] - Delete of object "mydomain.model.Product@565f390" using statement "DELETE FROM PRODUCT WHERE ID=?" failed : Referential integrity constraint violation: "PRODUCT_FK1: PUBLIC.PRODUCT FOREIGN KEY(INVENTORY_INVENTORY_NAME_EID) REFERENCES PUBLIC.INVENTORY(NAME) ('My Inventory')"; SQL statement:
DELETE FROM INVENTORY WHERE "NAME"=? [23503-168]
18:31:45,057 (main) DEBUG [DataNucleus.Persistence] - ExecutionContext.internalFlush() END
18:31:45,058 (main) DEBUG [DataNucleus.Transaction] - Delete of object "mydomain.model.Product@565f390" using statement "DELETE FROM PRODUCT WHERE ID=?" failed : Referential integrity constraint violation: "PRODUCT_FK1: PUBLIC.PRODUCT FOREIGN KEY(INVENTORY_INVENTORY_NAME_EID) REFERENCES PUBLIC.INVENTORY(NAME) ('My Inventory')"; SQL statement:
DELETE FROM INVENTORY WHERE "NAME"=? [23503-168]
org.datanucleus.exceptions.NucleusDataStoreException: Delete of object "mydomain.model.Product@565f390" using statement "DELETE FROM PRODUCT WHERE ID=?" failed : Referential integrity constraint violation: "PRODUCT_FK1: PUBLIC.PRODUCT FOREIGN KEY(INVENTORY_INVENTORY_NAME_EID) REFERENCES PUBLIC.INVENTORY(NAME) ('My Inventory')"; SQL statement:
DELETE FROM INVENTORY WHERE "NAME"=? [23503-168]
    at org.datanucleus.store.rdbms.request.DeleteRequest.execute(DeleteRequest.java:378)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObjectFromTable(RDBMSPersistenceHandler.java:494)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObject(RDBMSPersistenceHandler.java:466)
    at org.datanucleus.state.StateManagerImpl.internalDeletePersistent(StateManagerImpl.java:1207)
    at org.datanucleus.state.StateManagerImpl.flush(StateManagerImpl.java:5789)
    at org.datanucleus.flush.FlushOrdered.execute(FlushOrdered.java:132)
    at org.datanucleus.ExecutionContextImpl.flushInternal(ExecutionContextImpl.java:4063)
    at org.datanucleus.ExecutionContextImpl.flush(ExecutionContextImpl.java:4009)
    at org.datanucleus.ExecutionContextImpl.preCommit(ExecutionContextImpl.java:4184)
    at org.datanucleus.ExecutionContextImpl.transactionPreCommit(ExecutionContextImpl.java:729)
    at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:397)
    at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287)
    at org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:107)
    at org.datanucleus.test.SimpleTest.testSimple(SimpleTest.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:113)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: org.h2.jdbc.JdbcBatchUpdateException: Referential integrity constraint violation: "PRODUCT_FK1: PUBLIC.PRODUCT FOREIGN KEY(INVENTORY_INVENTORY_NAME_EID) REFERENCES PUBLIC.INVENTORY(NAME) ('My Inventory')"; SQL statement:
DELETE FROM INVENTORY WHERE "NAME"=? [23503-168]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1121)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.ParamLoggingPreparedStatement.executeBatch(ParamLoggingPreparedStatement.java:366)
    at org.datanucleus.store.rdbms.SQLController.processConnectionStatement(SQLController.java:667)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:233)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:176)
    at org.datanucleus.store.rdbms.request.DeleteRequest.execute(DeleteRequest.java:289)
    ... 42 more
Nested Throwables StackTrace:
org.h2.jdbc.JdbcBatchUpdateException: Referential integrity constraint violation: "PRODUCT_FK1: PUBLIC.PRODUCT FOREIGN KEY(INVENTORY_INVENTORY_NAME_EID) REFERENCES PUBLIC.INVENTORY(NAME) ('My Inventory')"; SQL statement:
DELETE FROM INVENTORY WHERE "NAME"=? [23503-168]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1121)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.ParamLoggingPreparedStatement.executeBatch(ParamLoggingPreparedStatement.java:366)
    at org.datanucleus.store.rdbms.SQLController.processConnectionStatement(SQLController.java:667)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:233)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:176)
    at org.datanucleus.store.rdbms.request.DeleteRequest.execute(DeleteRequest.java:289)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObjectFromTable(RDBMSPersistenceHandler.java:494)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObject(RDBMSPersistenceHandler.java:466)
    at org.datanucleus.state.StateManagerImpl.internalDeletePersistent(StateManagerImpl.java:1207)
    at org.datanucleus.state.StateManagerImpl.flush(StateManagerImpl.java:5789)
    at org.datanucleus.flush.FlushOrdered.execute(FlushOrdered.java:132)
    at org.datanucleus.ExecutionContextImpl.flushInternal(ExecutionContextImpl.java:4063)
    at org.datanucleus.ExecutionContextImpl.flush(ExecutionContextImpl.java:4009)
    at org.datanucleus.ExecutionContextImpl.preCommit(ExecutionContextImpl.java:4184)
    at org.datanucleus.ExecutionContextImpl.transactionPreCommit(ExecutionContextImpl.java:729)
    at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:397)
    at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287)
    at org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:107)
    at org.datanucleus.test.SimpleTest.testSimple(SimpleTest.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:113)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "PRODUCT_FK1: PUBLIC.PRODUCT FOREIGN KEY(INVENTORY_INVENTORY_NAME_EID) REFERENCES PUBLIC.INVENTORY(NAME) ('My Inventory')"; SQL statement:
DELETE FROM INVENTORY WHERE "NAME"=? [23503-168]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
    at org.h2.message.DbException.get(DbException.java:169)
    at org.h2.message.DbException.get(DbException.java:146)
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:414)
    at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:431)
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:307)
    at org.h2.table.Table.fireConstraints(Table.java:871)
    at org.h2.table.Table.fireAfterRow(Table.java:888)
    at org.h2.command.dml.Delete.update(Delete.java:99)
    at org.h2.command.CommandContainer.update(CommandContainer.java:75)
    at org.h2.command.Command.executeUpdate(Command.java:230)
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:156)
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1106)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.ParamLoggingPreparedStatement.executeBatch(ParamLoggingPreparedStatement.java:366)
    at org.datanucleus.store.rdbms.SQLController.processConnectionStatement(SQLController.java:667)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:233)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:176)
    at org.datanucleus.store.rdbms.request.DeleteRequest.execute(DeleteRequest.java:289)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObjectFromTable(RDBMSPersistenceHandler.java:494)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObject(RDBMSPersistenceHandler.java:466)
    at org.datanucleus.state.StateManagerImpl.internalDeletePersistent(StateManagerImpl.java:1207)
    at org.datanucleus.state.StateManagerImpl.flush(StateManagerImpl.java:5789)
    at org.datanucleus.flush.FlushOrdered.execute(FlushOrdered.java:132)
    at org.datanucleus.ExecutionContextImpl.flushInternal(ExecutionContextImpl.java:4063)
    at org.datanucleus.ExecutionContextImpl.flush(ExecutionContextImpl.java:4009)
    at org.datanucleus.ExecutionContextImpl.preCommit(ExecutionContextImpl.java:4184)
    at org.datanucleus.ExecutionContextImpl.transactionPreCommit(ExecutionContextImpl.java:729)
    at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:397)
    at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287)
    at org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:107)
    at org.datanucleus.test.SimpleTest.testSimple(SimpleTest.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:113)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "PRODUCT_FK1: PUBLIC.PRODUCT FOREIGN KEY(INVENTORY_INVENTORY_NAME_EID) REFERENCES PUBLIC.INVENTORY(NAME) ('My Inventory')"; SQL statement:
DELETE FROM INVENTORY WHERE "NAME"=? [23503-168]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
    at org.h2.message.DbException.get(DbException.java:169)
    at org.h2.message.DbException.get(DbException.java:146)
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:414)
    at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:431)
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:307)
    at org.h2.table.Table.fireConstraints(Table.java:871)
    at org.h2.table.Table.fireAfterRow(Table.java:888)
    at org.h2.command.dml.Delete.update(Delete.java:99)
    at org.h2.command.CommandContainer.update(CommandContainer.java:75)
    at org.h2.command.Command.executeUpdate(Command.java:230)
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:156)
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1106)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.datasource.dbcp2.DelegatingStatement.executeBatch(DelegatingStatement.java:345)
    at org.datanucleus.store.rdbms.ParamLoggingPreparedStatement.executeBatch(ParamLoggingPreparedStatement.java:366)
    at org.datanucleus.store.rdbms.SQLController.processConnectionStatement(SQLController.java:667)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:233)
    at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:176)
    at org.datanucleus.store.rdbms.request.DeleteRequest.execute(DeleteRequest.java:289)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObjectFromTable(RDBMSPersistenceHandler.java:494)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObject(RDBMSPersistenceHandler.java:466)
    at org.datanucleus.state.StateManagerImpl.internalDeletePersistent(StateManagerImpl.java:1207)
    at org.datanucleus.state.StateManagerImpl.flush(StateManagerImpl.java:5789)
    at org.datanucleus.flush.FlushOrdered.execute(FlushOrdered.java:132)
    at org.datanucleus.ExecutionContextImpl.flushInternal(ExecutionContextImpl.java:4063)
    at org.datanucleus.ExecutionContextImpl.flush(ExecutionContextImpl.java:4009)
    at org.datanucleus.ExecutionContextImpl.preCommit(ExecutionContextImpl.java:4184)
    at org.datanucleus.ExecutionContextImpl.transactionPreCommit(ExecutionContextImpl.java:729)
    at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:397)
    at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287)
    at org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:107)
    at org.datanucleus.test.SimpleTest.testSimple(SimpleTest.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:113)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)

При изменении отображаемого поля на Inventory-Type (не более интерфейса) главное также успешно работает в режиме Optimisti c.

@PersistenceCapable
public class Product
{
    @PrimaryKey
    @Persistent(valueStrategy=IdGeneratorStrategy.NATIVE)
    protected long id;

    protected Inventory inventory=null;

    ...
}

Что я пропустил? Что я делаю не так?

Заранее спасибо за помощь!

...