|
Home > Archive > Apache JDO Project > March 2006 > serialize Detachable instance for storage
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
serialize Detachable instance for storage
|
|
| Erik Bengtson 2006-03-17, 5:45 pm |
| Hi,
If we serialize a detachable instance for storage, does it have the detach state
populated? It is at least a waste of space.
Regards
| |
| Craig L Russell 2006-03-23, 8:46 pm |
| | |
| Erik Bengtson 2006-03-23, 8:46 pm |
| Hi Craig,
> On Mar 17, 2006, at 11:40 AM, Erik Bengtson wrote:
>
>
> Yes. Regardless of whether it's currently managed or already
> detached, the detached state is part of the serialized state of the
> instance.
>
>
> I don't understand how the detached state is wasted space. It
> contains information that's needed if the instance is in future
> attached to a persistence manager.
>
Let me ask differently: say a class A { B b; // detachable and serialized="true"
}
When you store an instance of A with a ref to B, B is serialized with detached
flags, but there is no utility of adding detached flags during serialization of
B because its purpose is to store in the database. So IMO, we should not add
detached flags in serialized stored instances.
So, it is a waste of space in the database.
| |
| Matthew T. Adams 2006-03-25, 9:46 am |
| Hi Erik,
I now understand your issue. If you declare a PC class that is =
detachable
to also be serialized in another class, how do you prevent the =
detachment
algorithm from running when the instance is being =
serialized/deserialized
for the purposes of persistent storage versus being =
serialized/deserialized
for any other reason? After all, the desired behavior, I think, is to =
store
embedded serialized instances as they are in their current state, not in =
a
detached-clean or detached-dirty state. Here is an example that I think
illustrates the issue:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
// Class foo.Person
package foo;
public class Person {
protected Address address;
// other fields...
}
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
// Class foo.Address
package foo;
public class Address {
// fields...
}
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
<!-- metadata file foo/package.jdo -->
<jdo>
<package name=3D"foo">
<class name=3D"Person" detachable=3D"true">
<field name=3D"Address" serialized=3D"true"/> <!-- note =
serialized
attribute here -->
</class>
<class name=3D"Address" detachable=3D"true"> <!-- note =
detachable
attribute here -->
</class>
</package>
</jdo>
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
// Some client code
public void testPersistNewSerializedAddressInstance(
) {
PersistenceManagerFactory pmf =3D
JDOHelper.getPersistenceManagerFactory("pmf.properties");
pmf.setDetachAllOnCommit(true);
PersistenceManager pm =3D pmf.getPersistenceManager();
pm.currentTransaction().begin();
Person person =3D new Person();
pm.makePersistent(person);
Address address =3D new Address();
person.setAddress(address);
pm.currentTransaction().commit();
// Q1: During storage, 'address' will be serialized, due to
metadata requirement, and serialized objects are
// implicitly detached according to spec section 12.6.8. Is the
address stored in the database detached? In
// other words, does the serialized form of the Address instance
stored in the database contain detachment
// information?
// Q2: Does 'address' reference a detached instance now because =
of
serialization of Person.address?
// Q3: Does 'person.address =3D=3D address' return true?
}
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
There are other scenarios that should probably be clarified as well, in
particular, when an Address is loaded from the data store, it is
deserialized. According to the spec, deserialized detached instances =
are in
one of the detached states (detached-clean, detached-dirty). Does that
mean, then, that an Address deserialized from the data store is
detached-clean or persistent-clean?
--matthew
>-----Original Message-----
>From: Erik Bengtson [mailto:erik@jpox.org]=20
>Sent: Thursday, March 23, 2006 10:47 AM
>To: JDO Expert Group; Apache JDO project
>Subject: Re: serialize Detachable instance for storage
>
>
>Hi Craig,
>
>
>Let me ask differently: say a class A { B b; // detachable and=20
>serialized=3D"true"
>}
>
>When you store an instance of A with a ref to B, B is=20
>serialized with detached
>flags, but there is no utility of adding detached flags during=20
>serialization of
>B because its purpose is to store in the database. So IMO, we=20
>should not add
>detached flags in serialized stored instances.
>
>So, it is a waste of space in the database.
>
| |
| Andy Jefferson 2006-03-25, 9:46 am |
| Hi,
> I now understand your issue. If you declare a PC class that is detachable
> to also be serialized in another class, how do you prevent the detachment
> algorithm from running when the instance is being serialized/deserialized
> for the purposes of persistent storage versus being serialized/deserialized
> for any other reason? After all, the desired behavior, I think, is to store
> embedded serialized instances as they are in their current state, not in a
> detached-clean or detached-dirty state.
Agreed. Storage in a datastore and retrieval from the datastore should be
transparent to the user, and should not involve detachment.
> // Q1: During storage, 'address' will be serialized, due to metadata requirement
> and serialized objects are implicitly detached according to spec section 12.6.8.
> Is the address stored in the database detached?
I say no.
> // Q2: Does 'address' reference a detached instance now because of
> serialization of Person.address?
I say no.
> Does that mean then, that an Address deserialized from the data store is
> detached-clean or persistent-clean?
persistent-clean. If the user updates a field on a serialised PC object, whilst
within the txn, they would expect it to make it into the datastore. If the object
is detached it has no StateManager and so any change will not be persisted.
The implementation can easily detect when it is serialising an object for storage
in the datastore (as opposed to any normal call to StateManager.preSerialize()),
and JPOX CVS currently assumes that the storage of serialised PC's does *not*
contain the detach state.
PS. There are no TCK tests that check on this currently, as noticed when we had
implemented it in a pure JDO2 spec way, detaching all serialised objects. JPOX
does however have its own unit tests that do check this situation.
--
Andy
| |
| Matthew T. Adams 2006-03-25, 9:46 am |
| I agree on all points, Andy. Craig, I would think it to be beneficial to
explicitly state something about what compliant implementations should do
when serializing instances for the purposes of embedded storage versus for
any other reason.
It is not currently discussed, although it does seem intutive for the JDO
implementation to handle this situation correctly.
--matthew
>-----Original Message-----
>From: Andy Jefferson [mailto:andy@jpox.org]
>Sent: Friday, March 24, 2006 11:51 AM
>To: jdo-dev@db.apache.org; jdo-experts-ext@sun.com
>Subject: RE: serialize Detachable instance for storage
>
>
>Hi,
>
>is detachable
>the detachment
>serialized/deserialized
>serialized/deserialized
>think, is to store
>state, not in a
>
>Agreed. Storage in a datastore and retrieval from the
>datastore should be
>transparent to the user, and should not involve detachment.
>
>metadata requirement
>spec section 12.6.8.
>
>I say no.
>
>
>I say no.
>
>data store is
>
>persistent-clean. If the user updates a field on a serialised
>PC object, whilst
>within the txn, they would expect it to make it into the
>datastore. If the object
>is detached it has no StateManager and so any change will not
>be persisted.
>
>
>The implementation can easily detect when it is serialising an
>object for storage
>in the datastore (as opposed to any normal call to
>StateManager.preSerialize()),
>and JPOX CVS currently assumes that the storage of serialised
>PC's does *not*
>contain the detach state.
>
>PS. There are no TCK tests that check on this currently, as
>noticed when we had
>implemented it in a pure JDO2 spec way, detaching all
>serialised objects. JPOX
>does however have its own unit tests that do check this situation.
>
>--
>Andy
>
| |
| Craig L Russell 2006-03-25, 9:46 am |
| | |
| Andy Jefferson 2006-03-25, 9:46 am |
| Hi Craig,
> By the way, Andy, if you have a test case that you can point me to (I
> hope it's in the repository) we can add it to the TCK or at least
> implement the ideas contained therein.
A simple testcase that would have failed when we implemented it in a strict JDO2
spec way (always detaching a serialised object) is stored at
JPOX/Core/src/test/org/jpox/persistence/SerializationTest.java (testSerialisedPC)
To give you the code snippet it's very similar to Matthews example earlier except
we're also updating a field in the serialised object
// Persist an object with a serialised PC field
try
{
tx.begin();
SerialisedHolder holder = new SerialisedHolder("Holder(1)", new
SerialisedObject("My Description(1)"));
pm.makePersistent(holder);
// Update holder and serialised object fields to check that they
get to the datastore
holder.setName("Holder(2)");
holder.getSerialisedPC().setDescription("My Description(2)");
tx.commit();
holderId = pm.getObjectId(holder);
}
catch (Exception e)
{
e.printStackTrace();
LOG.error(e);
fail("Exception thrown while persisted object with serialised PC
field : " + e.getMessage());
}
finally
{
if (tx.isActive())
{
tx.rollback();
}
pm.close();
}
// Retrieve the object and check the contents
pm = pmf.getPersistenceManager();
tx = pm.currentTransaction();
try
{
tx.begin();
SerialisedHolder holder =
(SerialisedHolder)pm.getObjectById(holderId);
assertTrue("Holder of serialised PC could not be retrieved!",
holder != null);
assertTrue("Holder name is incorrect",
holder.getName().equals("Holder(2)"));
assertTrue("Retrieved holder has null serialised object!",
holder.getSerialisedPC() != null);
assertEquals("Retrieved serialised object description is
incorrect :",holder.getSerialisedPC().getDescription(), "My Description(2)");
// Update holder and serialised object fields to check that they
get to the datastore
holder.getSerialisedPC().setDescription("My Description(3)");
holder.setName("Holder(3)");
tx.commit();
}
catch (Exception e)
{
e.printStackTrace();
LOG.error(e);
fail("Exception thrown while retrieving object with serialised PC
field : " + e.getMessage());
}
finally
{
if (tx.isActive())
{
tx.rollback();
}
pm.close();
}
The part that would fail would be the assert on the "description" of the
serialised PC since the update would not have happened if it had been detached
when serialising it into the datastore in part 1 (before its update).
--
Andy
|
|
|
|
|