Database Reference
In-Depth Information
private static final long
serialVersionUID
= 2012021400L;
private String innerClassRevLvl = "20120214a";
If I release a revision later that same day, it might have these changed values (for example only,
these are usually modified independently and for different reasons):
private static final long
serialVersionUID
= 2012021401L;
private String innerClassRevLvl = "20120214b";
It may be obvious, but the
L
at the end of the value for
serialVersionUID
is part of the number and
indicates that it is a
long
value. It is a way of casting what would by default be interpreted as an integer to
another type of primitive value. Use an upper case
L
to keep from having the lower case
l
(ell) confused
with a
1
(one). There are other
literal
value casts that consist of suffixes (for example
f
for float) and
prefixes (for example
0x
for hexadecimal). Take one, as needed.
Deserialization and Version UID
Bringing an object back to life after serialization requires deserialization. But there is one huge
requirement for this to happen—a class definition for the object must exist in the JVM. This is a
requirement that is often overlooked or assumed in the documentation on serialization. Usually, an
application is responsible for serializing an object, and an equivalent application handles the
deserialization. The application has a class definition, perhaps in a separate
.class
file, or as an inner
class, and so it already knows how to build an object of the type being deserialized. The serialized object
does not contain all the details of the class definition; rather, it should be considered to only retain the
data or state of the object when serialized. To deserialize the object in a JVM, the existing class definition
must provide a skeleton on which to build the body of the object.
That all makes sense to us now, but consider this twist: We are going to deserialize the object in the
Oracle database, in a place where the application does not run. To do this, we do have to have the class
definition; so for each application, we will be storing the inner class definition (we'll see how we do that
later). In the case of the inner class,
InnerRevLvlClass
of
OracleJavaSecure
, the class definition is there
on the Oracle database because we create
OracleJavaSecure
on the server. For other applications, we
will have to create the inner class on the Oracle database.
In the interim between object serialization and deserialization, some non-structural changes may
be made to the class definition, and the Java compiler and runtime versions may continue to advance;
but we should be able, even ten years down the road, to deserialize our object. This is where the
serialVersionUID
member variable comes into play. At the outset of use of our serialized objects, we
may have no problem depending on the runtime calculation of the
suid
(another name for this value
when the
serialVersionUID
member does not exist.) However, as time progresses and things change, we
may begin to experience mismatches between what we've serialized and what we are attempting to
deserialize into.
We can avoid problems with serial version mismatches (caused by technological progress rather
than by changes to our classes) by simply encoding a
serialVersionUID
member, rather than relying on
the runtime calculation.
If we do make structural changes to our class definition, we will need to do the following two things:
1.
Change the
serialVersionUID
value in our class definition.
2.
Store a new version of the class definition in Oracle.
Note that this situation is different from the situation where we are only encoding a new
innerClassRevLvl
in our class definition. We will do that to handle application version changes (and
provide an updated list of Oracle connection strings.)