I have a client/server application that passes XML data representing an Object of type A to the server. JiBX unmarshals the XML into an A and Hibernate persists it.
A has several fields that represent reference data, one of which is called Status. I wanted the application to be able to use Status objects without having to fetch them from the database each time, so I implemented Status as a singleton, as follows:
Code:
public class Status implements java.io.Serializable {
private static final long serialVersionUID = 1L;
public static final Status NONE =
new Status(StatusName.NONE);
public static final Status INCOMPLETE_REQUEST =
new Status(StatusName.INCOMPLETE_REQUEST);
...
private enum StatusName { NONE(15),
INCOMPLETE_REQUEST(1),
...;
private final int id;
StatusName(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
}
private int id;
private StatusName name;
public Status() { }
private Status(StatusName name) {
this.name = name;
this.id = name.getId();
}
public int getId() {
return this.id;
}
public int hashCode() {
return this.name.hashCode();
}
public String toString() {
return this.name.toString();
}
public boolean equals(Object obj) {
return this == obj;
}
}
When JiBX encounters <status>None</status> in the XML it will convert it to Status.NONE. On the Hibernate side, Status is mapped as follows:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated May 31, 2007 6:03:55 PM by Hibernate Tools 3.2.0.b9 -->
<hibernate-mapping>
<class name="model.Status"
table="ts_statuses" mutable="false">
<id name="id" type="int" access="field">
<column name="id_status" />
<generator class="increment" />
</id>
<natural-id>
<property name="name" access="field">
<type name="model.EnumUserType">
<param name="enumClassName">
model.Status$StatusName
</param>
</type>
</property>
</natural-id>
</class>
</hibernate-mapping>
where EnumUserType is the version provided at
http://www.hibernate.org/272.html (the first one).
This was all working fine for quite some time; about a week ago I went through and fixed a bunch of compiler warnings mostly pertaining to generics and now I get a NonUniqueObjectException pointing to the Status object whenever I try to unmarshal and persist an object of type A. I can't be sure of the exact code change that caused it to break; however, I think the error isn't that unreasonable - if at some point after the initial call to saveOrUpdate(theA) Hibernate for some reason attempted to fetch a Status object from the database and load it into the session it would clash with the one that was already attached to the session because it was a part of the A that we were persisting. I guess I'd like to know if my attempt here was reasonable and perhaps requires a small fix or if it was a completely ignorant way of solving this problem and requires a much different solution.
Thanks,
Dan