You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Lachlan Deck <la...@gmail.com> on 2009/11/26 02:33:09 UTC

delete new --> transient?

Hi there,

just wondering why when deleting a new object that its status is being set to PeristenceState.TRANSIENT rather than DELETED?

@see ObjectContextDeleteAction#deleteNew(Persistent)
It also doesn't turn up in context.deletedObjects

So this all seems to make it more difficult to determine the state of an object.

Regardless of the rationale - what's the recommended way of determining if an object is deleted within the context?
Thanks.

with regards,
--

Lachlan Deck


Re: delete new --> transient?

Posted by Lachlan Deck <la...@gmail.com>.
On 02/12/2009, at 9:35 AM, Weddle, Anthony wrote:

> -----Original Message-----
> From: Lachlan Deck [mailto:lachlan.deck@gmail.com]
> 
>> Now, without creating objects in the first place you both have nothing to
>> validate (validateForSave) nor can you roll-back changes (should this have
>> been a previously persisted object). In either case, the controller/ui
>> doesn't care...
> 
> OK. So the main problem is roll-back.

It's 'a' feature. Not the main/only problem.

> Obviously, to validate an object, you need the object but there's no need to validate a deleted object,

Of course. It won't validate whilst transient, though validateForDelete is relevant otherwise.

> I would have thought (and, presumably, it wouldn't be deleted until analysed).

To provide immediate user feedback, validation is triggered after each event (for us).

> So what is the roll-back point? Is it the last persisted state of the objects?

Sure.

> If so, then you don't need to know the current state of the objects and can create whole new objects or read them from the database, as you did at the start of the processes.

That's not the problem I'm solving. But sure, if someone hits cancel then that will occur.

> If it is some intermediate state, that you need to roll back to, then you should store that state in the program, not the object context, as far as I can tell.

I've got it working using Cayenne as I believe it should (though still not 100% that it covers all transient possibilities). Intermixing non-object state and custom state wouldn't be preferable.

> The context is there because of Cayenne, not because of the logic in your program.

Well.... on this I'll admit that I come from EOF where this particular action/case didn't require as much, um, thinking :-) To put it another way, I understand your logic here I just don't completely agree with it :)

> Perhaps you can delay any deletion, in context terms, until you know what is ultimately going to be saved.

That's not practical. If a save action is triggered that needs further work to be done by the user (requiring a subsequent save) at which point are the deletions inserted? It doesn't work.

>>> From the program's point of view, it's clear that TRANSIENT can be
>>> treated exactly the same as DELETED, since they both mean that some
>>> persistable object previously created in the program has subsequently
>>> been deleted by the program.
> 
>> My point (and clarifying question, however) is that if TRANSIENT does not
>> always mean that ... and it's possible for objects to be transient in
>> other ways then that's not good enough. It'll do for now - but I'd like to
>> put code in the entity that works in all circumstances and not just for
>> this particular case.
> 
> Ah, well, if you really do need to use context state for your code, then that would have to be the question to those that know: what situations can result in an object state of TRANSIENT? Maybe you can confidently assume that TRANSIENT is the same as DELETED, from the program's point of view. If not, then you'll have to avoid using the context for the purposes of your application's logic.

Certainly I'd have to handle it otherwise... which would be a shame for it diminishes the transparency of dealing with creating/deleting/updating objects no matter their destination.

>>> From the database's point of view, the states can't be treated the same
>>> way; the DELETED object has to be deleted from the database, the
>>> TRANSIENT object was never in the database and can be ignored.
> 
>> That's the easy part, sure. But from user-code's point of view, we don't
>> care about the database. It's an abstraction. :-) Thinking in terms of the
>> database when using an orm ain't best practice (of course you need to at
>> times). Think in terms of objects.
> 
> Indeed. By the same token, it is perhaps unwise to use something (the object context) that exists purely because of the persistence framework, unless you are strictly coding persistence logic.

We are strictly coding persistence logic. Even sql has conditional statements that may or may not cause alterations to any rows... that's the key point that imho you're missing...

> If you ever change the persistence framework, it may be hard to untangle the old one from your code.

That's always going to be true I'm afraid.

Anyway, thanks for your input.

with regards,
--

Lachlan Deck


RE: delete new --> transient?

Posted by "Weddle, Anthony" <An...@bluescopesteel.com>.
-----Original Message-----
From: Lachlan Deck [mailto:lachlan.deck@gmail.com]

> Now, without creating objects in the first place you both have nothing to
> validate (validateForSave) nor can you roll-back changes (should this have
> been a previously persisted object). In either case, the controller/ui
> doesn't care...

OK. So the main problem is roll-back. Obviously, to validate an object, you need the object but there's no need to validate a deleted object, I would have thought (and, presumably, it wouldn't be deleted until analysed). So what is the roll-back point? Is it the last persisted state of the objects? If so, then you don't need to know the current state of the objects and can create whole new objects or read them from the database, as you did at the start of the processes. If it is some intermediate state, that you need to roll back to, then you should store that state in the program, not the object context, as far as I can tell. The context is there because of Cayenne, not because of the logic in your program. Perhaps you can delay any deletion, in context terms, until you know what is ultimately going to be saved.

>> From the program's point of view, it's clear that TRANSIENT can be
>> treated exactly the same as DELETED, since they both mean that some
>> persistable object previously created in the program has subsequently
>> been deleted by the program.

> My point (and clarifying question, however) is that if TRANSIENT does not
> always mean that ... and it's possible for objects to be transient in
> other ways then that's not good enough. It'll do for now - but I'd like to
> put code in the entity that works in all circumstances and not just for
> this particular case.

Ah, well, if you really do need to use context state for your code, then that would have to be the question to those that know: what situations can result in an object state of TRANSIENT? Maybe you can confidently assume that TRANSIENT is the same as DELETED, from the program's point of view. If not, then you'll have to avoid using the context for the purposes of your application's logic.

>> From the database's point of view, the states can't be treated the same
>> way; the DELETED object has to be deleted from the database, the
>> TRANSIENT object was never in the database and can be ignored.

> That's the easy part, sure. But from user-code's point of view, we don't
> care about the database. It's an abstraction. :-) Thinking in terms of the
> database when using an orm ain't best practice (of course you need to at
> times). Think in terms of objects.

Indeed. By the same token, it is perhaps unwise to use something (the object context) that exists purely because of the persistence framework, unless you are strictly coding persistence logic. If you ever change the persistence framework, it may be hard to untangle the old one from your code.

Tony



NOTICE - This message and any attached files may contain information that is confidential, legally privileged or proprietary. It is intended only for use by the intended recipient. If you are not the intended recipient or the person responsible for delivering the message to the intended recipient, be advised that you have received this message in error. Any dissemination, copying, use or re-transmission of this message or attachment, or the disclosure of any information therein, is strictly forbidden. BlueScope Steel Limited does not represent or guarantee that this message or attachment is free of errors, virus or interference.

If you have received this message in error please notify the sender immediately and delete the message. Any views expressed in this email are not necessarily the views of BlueScope Steel Limited.

Re: delete new --> transient?

Posted by Lachlan Deck <la...@gmail.com>.
On 02/12/2009, at 5:09 AM, Weddle, Anthony wrote:

> The confusing thing, in this exchange is why Lachlan would be concerned about an object which, on the face of it, should never have been constructed (since it was created and then deleted, before it was ever persisted), or why he would want to create objects to replace those that had been deleted.

Perhaps a real example will help clear up any confusion here. This is for ROP, btw.

So we have an interface which presents to the user a Payslip with a series of (i.e., toMany) paylines. Depending on the information supplied per-line the line will either be discarded or included. Unlike the web (at least web 1.0) this state can toggle frequently.

Now, without creating objects in the first place you both have nothing to validate (validateForSave) nor can you roll-back changes (should this have been a previously persisted object). In either case, the controller/ui doesn't care...

> From the program's point of view, it's clear that TRANSIENT can be treated exactly the same as DELETED, since they both mean that some persistable object previously created in the program has subsequently been deleted by the program.

My point (and clarifying question, however) is that if TRANSIENT does not always mean that ... and it's possible for objects to be transient in other ways then that's not good enough. It'll do for now - but I'd like to put code in the entity that works in all circumstances and not just for this particular case.

> From the database's point of view, the states can't be treated the same way; the DELETED object has to be deleted from the database, the TRANSIENT object was never in the database and can be ignored.

That's the easy part, sure. But from user-code's point of view, we don't care about the database. It's an abstraction. :-) Thinking in terms of the database when using an orm ain't best practice (of course you need to at times). Think in terms of objects.

with regards,
--

Lachlan Deck


RE: delete new --> transient?

Posted by "Weddle, Anthony" <An...@bluescopesteel.com>.
The confusing thing, in this exchange is why Lachlan would be concerned about an object which, on the face of it, should never have been constructed (since it was created and then deleted, before it was ever persisted), or why he would want to create objects to replace those that had been deleted.

>From the program's point of view, it's clear that TRANSIENT can be treated exactly the same as DELETED, since they both mean that some persistable object previously created in the program has subsequently been deleted by the program. From the database's point of view, the states can't be treated the same way; the DELETED object has to be deleted from the database, the TRANSIENT object was never in the database and can be ignored.

Tony



NOTICE - This message and any attached files may contain information that is confidential, legally privileged or proprietary. It is intended only for use by the intended recipient. If you are not the intended recipient or the person responsible for delivering the message to the intended recipient, be advised that you have received this message in error. Any dissemination, copying, use or re-transmission of this message or attachment, or the disclosure of any information therein, is strictly forbidden. BlueScope Steel Limited does not represent or guarantee that this message or attachment is free of errors, virus or interference.

If you have received this message in error please notify the sender immediately and delete the message. Any views expressed in this email are not necessarily the views of BlueScope Steel Limited.

Re: delete new --> transient?

Posted by Michael Gentry <mg...@masslight.net>.
On Mon, Nov 30, 2009 at 5:40 PM, Lachlan Deck <la...@gmail.com> wrote:
> On 28/11/2009, at 2:01 AM, Michael Gentry wrote:
>> On Thu, Nov 26, 2009 at 12:52 PM, Lachlan Deck <la...@gmail.com> wrote:
>>> But this still means that there's no 'general purpose' method that I'm aware of (e.g., in Cayenne 'the new static helper' ... ah, see, if you'd called it CayenneUtils or PersistentUtils there'd be no need for further clarification of what Cayenne refers to via email ;-)  which answers the basic question: 'is this object marked for deletion (regardless of whether it was previously persisted)?'
>>
>> Well, an object should only be marked for deletion if it needs to be
>> deleted (it exists in the DB).
>
> This all depends on what 'deleted' means. If deleted were strictly for persisted objects as you suggest then why is deleteObject the method used to make transient those objects for which the action of deleting does not apply?


The DataContext doesn't require the user to figure out if an object
has been persisted before they call deleteObject() on it.  Nor does
the DataContext throw an exception if they call deleteObject() on a
NEW object.  The user clearly specified they no longer wanted the
object to be stored by calling deleteObject() so the DataContext marks
it as TRANSIENT if it has never been persisted or DELETED if it has
been persisted.  The commitChanges() will ignore the TRANSIENT objects
in the DataContext.


> The problem is that you cannot tell the difference between deleted transients and non-deleted transients by looking at its state. Is there something in the framework that tells me that an object was previously added to the context but was afterwards 'deleted' from it and is now marked as transient?


I'm not exactly sure why you care if the TRANSIENT object had
deleteObject() called on it or not.  In general practice, though, the
object will not be TRANSIENT *unless* you call deleteObject() on it
and it is a brand new object.  One typically does not call
setPersistenceState() on objects.  And one typically creates the
object inside the DataContext (calling newObject()), which gives it a
NEW state initially.  If it has a persistence state of DELETED, you
know it was previously persisted.


>>> I simply want to know if an object is marked for deletion within the context. It should be simple like the question itself. :)    And to answer the question, because I need to know at a later point whether to replace the object with a new one.


An object is marked for deletion, from the physical database, if the
persistence state is DELETED.


>> If an object's persistence state is set to DELETED,
>> then the DC knows it needs to issue a DELETE to the DB on
>> commitChanges()
>
> Are you saying that it has no knowledge otherwise as to whether the object was previously persisted?
>
> It could also 'know' that if an object's persistence state is set to deleted and the object was not previously persisted then it issues no sql. :-)


The persistence state variable is used to identify this information.
TRANSIENT = not persisted (or persistable).


> As I understand it, an OC exists to abstract parent object stores from the user.. where that parent object store may or may not necessarily be a database. But this is all besides the point.


The ObjectContext/DataContext does more than abstract the backing
store.  It provides a workspace or sandbox for changes to be made and
then manages those changes within a transaction.  If you throw away
the context, no changes are done.  To me it is more like checking out
code from a repository (such as Subversion) into a workarea.  You can
checkout as many workareas (or contexts -- one or more for each user)
as you want and make changes in them, but unless you commit them, the
repository (or database) doesn't get updated and no one else will see
those changes.


> I'm just asking the question as to whether cayenne provides the information I'm after.


I think Cayenne, especially in practical terms, tells you what you want.

Hope that helps somewhat ...

mrg

Re: delete new --> transient?

Posted by Lachlan Deck <la...@gmail.com>.
On 28/11/2009, at 2:01 AM, Michael Gentry wrote:

> On Thu, Nov 26, 2009 at 12:52 PM, Lachlan Deck <la...@gmail.com> wrote:
>> On 27/11/2009, at 2:24 AM, Andrey Razumovsky wrote:
>> 
>>> Because for deleted objects DELETE query will be forced, and if you create
>>> (register), then delete (unregister) an object it looks like as if it was
>>> never registered in context.
>> 
>> This seems (to me, at least) to be implementation details of the framework that's overly exposed to general users ('cause you have to know the implementation details in order to make any use of those persistence states in any meaningful way.... e.g., what does transient mean? Well it depends.... What does deleted mean? Again it depends on other conditions.). Perhaps then PersistenceState should be private to the framework.
> 
> Sometimes application code needs access to this and making it private
> wouldn't help that matter.

Sure - it can be convenient to have access to internals.

>> But this still means that there's no 'general purpose' method that I'm aware of (e.g., in Cayenne 'the new static helper' ... ah, see, if you'd called it CayenneUtils or PersistentUtils there'd be no need for further clarification of what Cayenne refers to via email ;-)  which answers the basic question: 'is this object marked for deletion (regardless of whether it was previously persisted)?'
> 
> Well, an object should only be marked for deletion if it needs to be
> deleted (it exists in the DB).

This all depends on what 'deleted' means. If deleted were strictly for persisted objects as you suggest then why is deleteObject the method used to make transient those objects for which the action of deleting does not apply?

> So Cayenne is working properly in this
> regard.

I'm not suggesting it's not behaving as expected.

> If an object has never been persisted (does NOT exist in the
> DB), then it is marked as transient if you delete it.

The problem is that you cannot tell the difference between deleted transients and non-deleted transients by looking at its state. Is there something in the framework that tells me that an object was previously added to the context but was afterwards 'deleted' from it and is now marked as transient?

>> I simply want to know if an object is marked for deletion within the context. It should be simple like the question itself. :)    And to answer the question, because I need to know at a later point whether to replace the object with a new one.
> 
> By context I assume you mean data/object context.

Correct.

> My previous comment
> still applies.  :-)  The DataContext needs to know what to do when you
> commitChanges().

Of course it does.

> If an object's persistence state is set to DELETED,
> then the DC knows it needs to issue a DELETE to the DB on
> commitChanges()

Are you saying that it has no knowledge otherwise as to whether the object was previously persisted?

It could also 'know' that if an object's persistence state is set to deleted and the object was not previously persisted then it issues no sql. :-)

> Here is TRANSIENT:
> 
>    /**
>     * Describes a state of an object not registered with
> DataContext/ObjectContext, and
>     * therefore having no persistence features.
>     */
>    public static final int TRANSIENT = 1;
> 
> If you register an object with a DC and then delete it (without ever
> persisting it), then it becomes TRANSIENT.  If you register an object
> with a DC, commit it, then delete it, it becomes DELETED.  Keep in
> mind the DC exists to manage your objects for committing changes to
> the DB, not to track general Java usage (such as removing an object
> from a collection).

As I understand it, an OC exists to abstract parent object stores from the user.. where that parent object store may or may not necessarily be a database. But this is all besides the point. 

I'm just asking the question as to whether cayenne provides the information I'm after.

with regards,
--

Lachlan Deck


Re: delete new --> transient?

Posted by Michael Gentry <mg...@masslight.net>.
On Thu, Nov 26, 2009 at 12:52 PM, Lachlan Deck <la...@gmail.com> wrote:
> On 27/11/2009, at 2:24 AM, Andrey Razumovsky wrote:
>
>> Because for deleted objects DELETE query will be forced, and if you create
>> (register), then delete (unregister) an object it looks like as if it was
>> never registered in context.
>
> This seems (to me, at least) to be implementation details of the framework that's overly exposed to general users ('cause you have to know the implementation details in order to make any use of those persistence states in any meaningful way.... e.g., what does transient mean? Well it depends.... What does deleted mean? Again it depends on other conditions.). Perhaps then PersistenceState should be private to the framework.


Sometimes application code needs access to this and making it private
wouldn't help that matter.


> But this still means that there's no 'general purpose' method that I'm aware of (e.g., in Cayenne 'the new static helper' ... ah, see, if you'd called it CayenneUtils or PersistentUtils there'd be no need for further clarification of what Cayenne refers to via email ;-)  which answers the basic question: 'is this object marked for deletion (regardless of whether it was previously persisted)?'


Well, an object should only be marked for deletion if it needs to be
deleted (it exists in the DB).  So Cayenne is working properly in this
regard.  If an object has never been persisted (does NOT exist in the
DB), then it is marked as transient if you delete it.


> I simply want to know if an object is marked for deletion within the context. It should be simple like the question itself. :)    And to answer the question, because I need to know at a later point whether to replace the object with a new one.


By context I assume you mean data/object context.  My previous comment
still applies.  :-)  The DataContext needs to know what to do when you
commitChanges().  If an object's persistence state is set to DELETED,
then the DC knows it needs to issue a DELETE to the DB on
commitChanges() (TRANSIENT objects will not be persisted).  The
JavaDoc even specifies this:

    /**
     * Describes a state of an object registered with
DataContext/ObjectContext, that will
     * be deleted from the database on the next commit.
     */
    public static final int DELETED = 6;

Here is TRANSIENT:

    /**
     * Describes a state of an object not registered with
DataContext/ObjectContext, and
     * therefore having no persistence features.
     */
    public static final int TRANSIENT = 1;

If you register an object with a DC and then delete it (without ever
persisting it), then it becomes TRANSIENT.  If you register an object
with a DC, commit it, then delete it, it becomes DELETED.  Keep in
mind the DC exists to manage your objects for committing changes to
the DB, not to track general Java usage (such as removing an object
from a collection).

mrg

Re: delete new --> transient?

Posted by Lachlan Deck <la...@gmail.com>.
On 27/11/2009, at 2:24 AM, Andrey Razumovsky wrote:

> Because for deleted objects DELETE query will be forced, and if you create
> (register), then delete (unregister) an object it looks like as if it was
> never registered in context.

This seems (to me, at least) to be implementation details of the framework that's overly exposed to general users ('cause you have to know the implementation details in order to make any use of those persistence states in any meaningful way.... e.g., what does transient mean? Well it depends.... What does deleted mean? Again it depends on other conditions.). Perhaps then PersistenceState should be private to the framework.

But this still means that there's no 'general purpose' method that I'm aware of (e.g., in Cayenne 'the new static helper' ... ah, see, if you'd called it CayenneUtils or PersistentUtils there'd be no need for further clarification of what Cayenne refers to via email ;-)  which answers the basic question: 'is this object marked for deletion (regardless of whether it was previously persisted)?'

> Why you need such testing?

I simply want to know if an object is marked for deletion within the context. It should be simple like the question itself. :)    And to answer the question, because I need to know at a later point whether to replace the object with a new one.

i.e., there's basic questions that are generally useful:
isNew, isModified, isDeleted.

> Currently I can think only of quite nasty
> workaround on ROP 3.0 - using custom contexts and overriding deleteObject()

I ended up having to do:
public boolean isDeleted() {
	return
	getObjectContext() == null
	|| getObjectContext().deletedObjects().contains(this)
	|| !getObjectContext().getGraphManager().registeredNodes().contains(getRecord());
}

It's a bit unintuitive imho for deletedObjects to not contain these things ... for surely they could be dealt with (i.e., treated as unregistered) during the saveChanges operations should an object be both new and deleted(?)....

> 2009/11/26 Lachlan Deck <la...@gmail.com>
> 
>> Hi there,
>> 
>> just wondering why when deleting a new object that its status is being set
>> to PeristenceState.TRANSIENT rather than DELETED?
>> 
>> @see ObjectContextDeleteAction#deleteNew(Persistent)
>> It also doesn't turn up in context.deletedObjects
>> 
>> So this all seems to make it more difficult to determine the state of an
>> object.
>> 
>> Regardless of the rationale - what's the recommended way of determining if
>> an object is deleted within the context?
>> Thanks.
>> 
>> with regards,
>> --
>> 
>> Lachlan Deck
>> 
>> 
> 
> 
> -- 
> Andrey

with regards,
--

Lachlan Deck




Re: delete new --> transient?

Posted by Andrey Razumovsky <ra...@gmail.com>.
Because for deleted objects DELETE query will be forced, and if you create
(register), then delete (unregister) an object it looks like as if it was
never registered in context.
Why you need such testing? Currently I can think only of quite nasty
workaround on ROP 3.0 - using custom contexts and overriding deleteObject()

2009/11/26 Lachlan Deck <la...@gmail.com>

> Hi there,
>
> just wondering why when deleting a new object that its status is being set
> to PeristenceState.TRANSIENT rather than DELETED?
>
> @see ObjectContextDeleteAction#deleteNew(Persistent)
> It also doesn't turn up in context.deletedObjects
>
> So this all seems to make it more difficult to determine the state of an
> object.
>
> Regardless of the rationale - what's the recommended way of determining if
> an object is deleted within the context?
> Thanks.
>
> with regards,
> --
>
> Lachlan Deck
>
>


-- 
Andrey