Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Switch between transient and persistent objects?

pokrakam
Active Contributor
0 Likes
2,143

Hi Folks,

I'm to ask this type of question, but couldn't find an answer.

Using persistent classes, does anyone know an elegant way to convert a transient object to a persistent one and vice versa? There is no standard functionality provided that I can see, and cloning the object results in clashing keys.

What am I trying to accomplish?

I need an object instance which <i>may</i> exist in the DB and if not, it <i>may</i> need to be saved for future use. I'm using a table with key fields K1 and K2 and the app will ask for an object instance using the full key K1+K2.

If the object doesn't find a DB record for K1K2 then it should instantiate itself with values for K1blank. Here is where I'm considering transient in order to provide the app with default functionality defined in record K1+blank.

If a write access occurs to a transient object then is should become persistent and the K1+K2 record be created.

Any ideas appreciated.

Cheers,

Mike

10 REPLIES 10
Read only

Former Member
0 Likes
1,658

Hi Mike,

You can call the create_persistent method with the attributes of the transient object except the business key. Then you will get a new business key for the persistent object. Then overwrite the reference to the transient object with the new persistent object reference.

Something like this.

MyTransientObject = Agent->Create_Transient( ... )

...

MyPersistentObject = Agent->Create_Persistent( ... ).

MyTransientObject ?= MyPersistentObject.

<b>Kindly reward points if you found the reply helpful.<b>

Cheers,

Chaitanya.

Read only

0 Likes
1,658

Well done on copying an irrelevant answer <b>from a link I provided</b>.

Replies are appreciated, but please try to understand the problem first.

Read only

former_member199581
Active Participant
0 Likes
1,658

Hi Mike,

I written something similar working on Persistent Objects.

The only point of attention is that you cannot create a new persistent while a transient is resident in memory.

This is checked by the OS system during the creation of a new persistent:

in method CREATE_PERSISTENT of Basis Class, there is a check on the existing object:


* Precondition   : No object exists with the given business key, neither
*                  in memory nor on database.

So, you can create a new transient, fill it with the values you need and then pass this values to the agent to create a new persistent, but only after releasing the existing transient (because they will have the same key).

I've solved the problem like this:


METHOD flush.
 "IMPORTING value(im_transient) TYPE REF TO zcl_liquidate_daily_bo
 "IMPORTING value(im_commit) TYPE xfeld
 "IMPORTING value(im_agent) TYPE REF TO zca_liquidate_daily_bo
 "RETURNING value(re_persistent) TYPE REF TO zcl_liquidate_daily_bo
 "--> raised by event PERNR_PROCESSED

  DATA: s_dip_liq TYPE zhr_tm_dip_liq.

  s_dip_liq-zpernr    = im_transient->get_employee_no( ).
  s_dip_liq-zsocmat   = im_transient->get_matricola_legale( ).
  s_dip_liq-zdataev   = im_transient->get_event_date( ).
  s_dip_liq-zcodev    = im_transient->get_event_type( ).
  s_dip_liq-zdescev   = im_transient->get_event_descr( ).
  s_dip_liq-zmotev    = im_transient->get_event_reasn( ).
  s_dip_liq-zmeseall  = im_transient->get_mese_allineamento( ).
  s_dip_liq-zannoall  = im_transient->get_anno_allineamento( ).

* // Invalidate the transient before create the persistent!
  im_agent->if_os_factory~release( im_transient ).
  CLEAR im_transient.

  IF im_commit EQ abap_true.
    TRY.
 re_persistent = 
 im_agent->create_persistent( EXPORTING i_anno_allineamento = s_dip_liq-zannoall
                                               i_mese_allineamento = s_dip_liq-zmeseall
                                               i_employee_no       = s_dip_liq-zpernr
                                               i_event_date        = s_dip_liq-zdataev
                                               i_event_type        = s_dip_liq-zcodev
                                               i_event_descr       = s_dip_liq-zdescev
                                               i_event_reasn       = s_dip_liq-zmotev
                                               i_matricola_legale  = s_dip_liq-zsocmat ).
      CATCH cx_os_object_existing.
    ENDTRY.
    COMMIT WORK AND WAIT.
  ENDIF.


ENDMETHOD.

This method is called inside a loop on a table that containes references to transient objects.

For each object I perform some tasks, and if all it's ok I raise the event PERNR_PROCESSED, which automatically calls this method FLUSH, transferring the transient to the persistent.

Return Object is the new persistent, which will be passed back to the internal table, changing the content from the transient to the new persistent.

Hope this helps,

Roby.

Read only

0 Likes
1,658

Hi Roby,

Thanks for the input, looks similar to the last resort avenues I've been investigating. Agreed, the conflicting keys make this a bit messy.

To sum it up: read the entire internal state of a transient object, delete it, create a persitent and feed it all the saved data.

More 'big hammer' than 'elegant' but if it works... I think I may try to implement it as transient_to_persistent( ) method in the agent class, will post back if it works.

I'll leave the thread open for a while to see if anyone has any better ideas.

Thanks,

Mike

Read only

0 Likes
1,658

Yes, I know that this is not so "elegant", but I had not so much time and I solved with this "brick"!

If fact, I tried to mask it using an event raise, but at the eyes of a developer...the hammer shows up.

If I can, I'll try to develop a transient_to_persistent too, so we can check solutions!

Read only

0 Likes
1,658

Indeed, I completely understand the brick theory Time is not my friend either at the moment. Pity, as it's an interesting problem worth investigating in more detail.

I discovered one other problem with this approach: I'm also trying to handle this completely inside the object to encapsulate the persistent/transient state. The app shouldn't care or even know what state is being used. The idea is that whenever anyone writes to a transient object using a set_whatever( ) method it converts itself to persistent.

If I recreate the object however, the reference to the old one must die before I can create a new one, so the app loses the link.

Catch 22?

Read only

pokrakam
Active Contributor
0 Likes
1,658

Just to post back my big hammer solution:

Created agent methods MAKE_PERSISTENT and MAKE_TRANSIENT according to code similar to the above.

During instantiation, the DB is checked. If only a partial match is found, the object is instantiated as transient with the full key.

The application must perform a

lv_myobj = zca_myclass=>agent->make_persistent( lv_myobj )

before doing any modifications to the object.

Not elegant, but at least the big hammer portion is limited to one line of code in the caller.

Alternate suggestions are of course always welcome.

Cheers,

Mike

Read only

Former Member
0 Likes
1,658

Hi Mike -- can't help you with the answer to your question but you have found the achilles heel of using OO with essentially a relational DB system. An OO related DB (ODBMS) would have this problem neatly solved however there aren't many robust Object Orientated DB systems around - certainly not for Enterprise strength applications like SAP.

In slightly different contexts I've found when creating Objects it seems a pain that there is no way to store these in a DB on SAP (or not until recently and even then it's a cludge as if any of the relational components change how do you automatically update the stored object) so you have to go through the whole process of instantiation and using the Constructor to re-create the attributes every time you want to (re-)use the object.

An example might be a Sales order --but instead of the traditional VBAK, VBAP, etc etc with different relational tables stored in the sap system you might have set the entire component up as a complete object with all the items, partners, delivery lines, texts, customer, invoice details etc.

In an OO DB system you would simply save the object; Instantiation will retrieve you the whole package again without any extra coding.

However if you apply this logic to the SAP system you can achieve some sort of object persistence --but if say a partner function or another attribute changes you need to make sure that BOTH the object and the relational table are updated in sync or you will be up that very well known street without a paddle.

I like the idea of persistent objects but in it's present form I think it can be only of very limited use rather than in a real robust application.

I suspect we'll here more on this topic as OO becomes more commonplace.

I can't as I've said answer your question but you might find this little diagression interesting.

Someone from Sap Laps if they read this post might like to post a link on to the current thinking in using an ODBMS in a future release of SAP . I can't see the current RDBMS (relational) system being phased out for a very long time if ever but there could be some degree of using both systems or even a hybrid type which contains aspects of both systems.

Cheers

Jimbo

Read only

pokrakam
Active Contributor
0 Likes
1,658

>

> In slightly different contexts I've found when creating Objects it seems a pain that there is no way to store these in a DB on SAP (or not until recently and even then it's a cludge as if any of the relational components change how do you automatically update the stored object) so you have to go through the whole process of instantiation and using the Constructor to re-create the attributes every time you want to (re-)use the object.

>

Easily done, search for IF_SERIALIZABLE_OBJECT. Nevermind database, you can store the state of an entire ZCL_ORDER with ZCL_ORDER_ITEM subcomponents in a cookie.

>

> I like the idea of persistent objects but in it's present form I think it can be only of very limited use rather than in a real robust application.

>

I actually think for the most part they have done a great job of it. I have a couple of gripes, one of the biggest being the division between persistent and transient states which is clumsy at best. Another is the way the of the DB access layer is implemented - far too embedded to do a huge amount of tweaking.

> I suspect we'll here more on this topic as OO becomes more commonplace.

>

Definitely.

Read only

Former Member
0 Likes
1,658

Hi Mike --whilst we've diverged a bit from the original problem I still think there are problems in data integrity in storing a persistent object if any of the attributes change -- especially if these attributes can be maintained totally separately from object itself.

In the sales order example I quoted above the partner functions / addresses can easily be changed via standard SAP transactions.

If I have a persistent object stored -- what mechanism do I have to use to ensure that the current attributes are identical to those just updated in SAP.

Instantiating my "Object" should just retrieve the whole object from the persistent area. There shouldn't need to be any extra coding to recover attributes etc.

If it has to re-calculate / obtain all the attributes again after instantiation then a significant benefit of saving the object as a persistent object is lost.

In an OBDMS if an attribute is chaged then the object itself is updated automatically.

I'm not sure how this would work in SAP given the relational nature of the underlying DB system

I'm looking at some (Non SAP) OBDMS systems just for playing around with -- a good one if you are interested in testing on a home computer is db4objects

web site is http://www.db4o.com/Default.aspx?AspxAutoDetectCookieSupport=1

Cheers

Jimbo