This problem is now a lot simplied (I did get a little confused when writing the report, my bad). Please read on:
I started lookin at the differences between node="organisationType" and node="organisationType/@id" on the many to one, because it's this that breaks the tx.commit() call. First though, I wrote a little dumpXml method - it's pretty boring, just a knocked together pretty printer for XML:
Code:
public Element testFunc(Session session) {
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Transaction tx = session.beginTransaction();
List results = dom4jSession.createQuery("from Organisation o where o.id=:id")
.setInteger("id", 17000)
.list();
Element root = (Element)results.get(0);
dumpXml(0, 3, root);
tx.commit();
return root;
}
public void dumpXml(int depth, int maxDepth, Element element) {
PrintStream out = System.out;
String prefix = "";
for (int i=0; i < depth; i++)
prefix += " ";
String endTag = prefix + "</" + element.getName() + ">";
out.print(prefix + "<" + element.getName());
List<Attribute> attrs = element.attributes();
if (attrs != null)
for (Attribute attr : attrs) {
out.print(" ");
out.print(attr.getName());
out.print('=');
out.print(attr.getValue());
}
out.println('>');
String text = element.getTextTrim();
if (text != null && text.length() > 0) {
out.print(" " + prefix + "<![CDATA[");
out.println(text + "]]>");
}
List<Element> children = element.elements();
prefix += " ";
if (children != null && depth < maxDepth) {
for (Element child : children) {
dumpXml(depth + 1, maxDepth, child);
}
}
out.println(endTag);
}
Without using "node" attribute on <many-to-one> at all, I get this:
Code:
<Organisation>
<id>
<![CDATA[17000]]>
</id>
<organisationType>
<id>
<![CDATA[14]]>
</id>
<description>
<![CDATA[Retailer]]>
</description>
<organisationTypeConstant>
<![CDATA[orgtypRetailer]]>
</organisationTypeConstant>
</organisationType>
<name>
<![CDATA[SPAR Corfe Mullen]]>
</name>
<lastUpdated>
<![CDATA[25 January 2006]]>
</lastUpdated>
<nameUpper>
<![CDATA[SPAR CORFE MULLEN]]>
</nameUpper>
</Organisation>
So far so good, everything as expected. So I added the node attribute (as per docs)
Code:
<many-to-one name="organisationType" class="uk.co.spar.db.OrganisationType" fetch="select" node="org-type/@id">
and re run the code. I get:
Code:
<Organisation>
<id>
<![CDATA[17000]]>
</id>
<org-type>
<id>
<id>
<![CDATA[14]]>
</id>
<description>
<![CDATA[Retailer]]>
</description>
<organisationTypeConstant>
<![CDATA[orgtypRetailer]]>
</organisationTypeConstant>
</id>
</org-type>
<name>
<![CDATA[SPAR Corfe Mullen]]>
</name>
<lastUpdated>
<![CDATA[25 January 2006]]>
</lastUpdated>
<nameUpper>
<![CDATA[SPAR CORFE MULLEN]]>
</nameUpper>
</Organisation>
It seems that node="org-type/@id" causes the element to be called "org-type" but creates a sub-
element called "id" (instead of an attribute), and in that "id" element is the contents of the correct element (ie "id", "description", etc elements).
If I change the "node" attribute to just "org-type", then the node is built correctly using the org-type tag name instead of organisationType, it's only when you add the "/@id" (as per the docs) that it falls appart and interprets this as an attempt to create a sub element.
One final test - changing the node to "org-type/my-id" causes this:
Code:
<Organisation>
<id>
<![CDATA[17000]]>
</id>
<org-type>
<y-id>
<id>
<![CDATA[14]]>
</id>
<description>
<![CDATA[Retailer]]>
</description>
<organisationTypeConstant>
<![CDATA[orgtypRetailer]]>
</organisationTypeConstant>
</y-id>
</org-type>
<name>
<![CDATA[SPAR Corfe Mullen]]>
</name>
<lastUpdated>
<![CDATA[25 January 2006]]>
</lastUpdated>
<nameUpper>
<![CDATA[SPAR CORFE MULLEN]]>
</nameUpper>
</Organisation>
Note that it still creates a sub-element, although this time you'd expect it to because you've specified so("node='org-type/my-id'") but the first character of "my-id" is missing.
Summary
When using node and embed-xml="true" do not use 'node="sometag/@id", it gives a strange and non-reversable structure.
When embed-xml="false" you can use either 'node="sometag"' or 'node="sometag/@id"' - the first form puts the id in as a child text node, the second as an attribute of the child - but in either case they pass back though tx.commit() successfully.
I'm about to start debugging the part where the value of the node attribute is interpretted - any leg-ups on where to look would be real helpful.
Regards,
John