Problem deleting one side of m:n bi-directional CMR
kkokal Jul 26, 2005 2:09 PMI have what seems to be a very straight-forward scenario, but I'm experiencing a problem I can't find a solution for.
Two EJB2 CMP entity beans (generated w/ xdoclet) participate in an m:n bi-directional relationship:
MSide (backed by DB table 'mside', primary key 'id')
NSide (backed by DB table 'nside', primary key 'id')
The relation table in the DB ('mn') contains constrained FK columns mid and nid.
When I call mside.remove(), I get a RemoveException (DELETE statement conflicted with COLUMN REFERENCE constraint 'FK_MN_MSide'. The conflict occurred in database 'jboss_dev', table 'MN', column 'mid'.) because the CMP engine is trying to delete the MSide row before it deletes the relationship row from the 'MN' table. How do I indicate that the relationship should be deleted first?
Regards,
Kevin Kokal
Environment:
JBoss 4.0.2
MS SQL Server
JTDS 1.1 JDBC driver
ejb-jar.xml snippet:
[CDATA[Description for MSide]]
<display-name>Name for MSide</display-name>
<ejb-name>MSide</ejb-name>
test.bugs.deletemanytomany.MSideHome
test.bugs.deletemanytomany.MSide
<local-home>test.bugs.deletemanytomany.MSideLocalHome</local-home>
test.bugs.deletemanytomany.MSideLocal
<ejb-class>test.bugs.deletemanytomany.MSideCMP</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.Long</prim-key-class>
False
<cmp-version>2.x</cmp-version>
<abstract-schema-name>MSide</abstract-schema-name>
<cmp-field >
[CDATA[]]
<field-name>id</field-name>
</cmp-field>
<primkey-field>id</primkey-field>
[CDATA[Description for NSide]]
<display-name>Name for NSide</display-name>
<ejb-name>NSide</ejb-name>
test.bugs.deletemanytomany.NSideHome
test.bugs.deletemanytomany.NSide
<local-home>test.bugs.deletemanytomany.NSideLocalHome</local-home>
test.bugs.deletemanytomany.NSideLocal
<ejb-class>test.bugs.deletemanytomany.NSideCMP</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.Long</prim-key-class>
False
<cmp-version>2.x</cmp-version>
<abstract-schema-name>NSide</abstract-schema-name>
<cmp-field >
[CDATA[]]
<field-name>id</field-name>
</cmp-field>
<primkey-field>id</primkey-field>
<ejb-relation >
<ejb-relation-name>m-n</ejb-relation-name>
<ejb-relationship-role >
<ejb-relationship-role-name>theNSide</ejb-relationship-role-name>
Many
<relationship-role-source >
<ejb-name>NSide</ejb-name>
</relationship-role-source>
<cmr-field >
<cmr-field-name>theMSides</cmr-field-name>
<cmr-field-type>java.util.Collection</cmr-field-type>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role >
<ejb-relationship-role-name>theMSide</ejb-relationship-role-name>
Many
<relationship-role-source >
<ejb-name>MSide</ejb-name>
</relationship-role-source>
<cmr-field >
<cmr-field-name>theNSides</cmr-field-name>
<cmr-field-type>java.util.Collection</cmr-field-type>
</cmr-field>
</ejb-relationship-role>
</ejb-relation>
jboss.xml:
<ejb-name>NSide</ejb-name>
<jndi-name>ejb/NSide</jndi-name>
<local-jndi-name>NSideLocal</local-jndi-name>
<configuration-name>Standard CMP 2.x EntityBean</configuration-name>
<method-attributes></method-attributes>
<ejb-name>MSide</ejb-name>
<jndi-name>ejb/MSide</jndi-name>
<local-jndi-name>MSideLocal</local-jndi-name>
<configuration-name>Standard CMP 2.x EntityBean</configuration-name>
<method-attributes></method-attributes>
jbosscmp-jdbc.xml:
<ejb-relation>
<ejb-relation-name>m-n</ejb-relation-name>
<relation-table-mapping>
<table-name>mn</table-name>
<create-table>false</create-table>
<remove-table>false</remove-table>
</relation-table-mapping>
<ejb-relationship-role>
<ejb-relationship-role-name>theNSide</ejb-relationship-role-name>
<key-fields>
<key-field>
<field-name>id</field-name>
<column-name>nId</column-name>
</key-field>
</key-fields>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>theMSide</ejb-relationship-role-name>
<key-fields>
<key-field>
<field-name>id</field-name>
<column-name>mId</column-name>
</key-field>
</key-fields>
</ejb-relationship-role>
</ejb-relation>
IMPORTANT:
Note that the "Standard CMP 2.x EntityBean" specified in jboss.xml is NOT the default config of the same name, but rather a renamed copy of the Instance Per Transaction config. Here is the config from standardjboss.xml:
<container-configuration>
<container-name>Standard CMP 2.x EntityBean</container-name>
<!--container-name>Instance Per Transaction CMP 2.x EntityBean</container-name-->
<call-logging>true</call-logging>
<invoker-proxy-binding-name>entity-rmi-invoker</invoker-proxy-binding-name>
<sync-on-commit-only>true</sync-on-commit-only>
<insert-after-ejb-post-create>true</insert-after-ejb-post-create>
<call-ejb-store-on-clean>true</call-ejb-store-on-clean>
<container-interceptors>
org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor
org.jboss.ejb.plugins.LogInterceptor
org.jboss.ejb.plugins.SecurityInterceptor
org.jboss.ejb.plugins.TxInterceptorCMT
org.jboss.ejb.plugins.CallValidationInterceptor
org.jboss.ejb.plugins.MetricsInterceptor
org.jboss.ejb.plugins.EntityCreationInterceptor
org.jboss.ejb.plugins.EntityLockInterceptor
org.jboss.ejb.plugins.EntityInstanceInterceptor
org.jboss.ejb.plugins.EntityReentranceInterceptor
org.jboss.resource.connectionmanager.CachedConnectionInterceptor
org.jboss.ejb.plugins.EntitySynchronizationInterceptor
org.jboss.ejb.plugins.cmp.jdbc.JDBCRelationInterceptor
</container-interceptors>
<instance-pool>org.jboss.ejb.plugins.EntityInstancePool</instance-pool>
<instance-cache>org.jboss.ejb.plugins.PerTxEntityInstanceCache</instance-cache>
<persistence-manager>org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager</persistence-manager>
<locking-policy>org.jboss.ejb.plugins.lock.NoLock</locking-policy>
<container-cache-conf/>
<container-pool-conf>
100
</container-pool-conf>
<commit-option>C</commit-option>
</container-configuration>