Skip to Content
Introduction
This weblog was really sparked by a conversation that I had the other day. I was talking with a Java developer who was fairly new to the SAP world, but claimed to already be an ABAP expert. He was commenting on the ABAP programming language. Several of his comments revolved around the fact that ABAP Objects didn’t have persistent objects or an OO transactional system. Now I found this rather interesting considering that ABAP Objects does have both of those things.

On the same day that I had the opportunity to set this poor misguided soul straight, I ran into another instance of persistence ignorance. There was a posting in SDN on the ABAP forum asking ABAP Developers to fill out /thread/21300 [original link is broken]. One of the questions is “What are the weak points for ABAP Objects”. The possible answer that struck me was – “No persistent objects or serializeable objects”. ABAP objects actually has both persistent and serializeable objects. 5 people out of 45 so far had given this option as a weak point for ABAP Objects. Therefore I dedicate this weblog to those 5 people and my Java friend.

Serializeable Objects
In defense of those who answered that the lack of persistence and serializeable objects was a weakness, it is true that this functionality is not present before the 6.X releases of the WebAS. All the examples that I am going to share today were developed on a 620 WebAS. Before I jump into the heart of the weblog on Persistent Objects, I thought I might address serializeable objects once again real quick. If you want an ABAP Object class to be serializeable, all you have to do is add the IF_SERIALIZABLE_OBJECT interface. That’s it – pretty simple!. The following is some sample ABAP code that I have to serialize a data object class and write it out to an XML file on the presentation server:

The resulting XML looks like this:

image

Persistent Objects
For this section on Persistent Objects I am going to take a chapter from a delta training course I wrote for in house development group. We are going to start off by creating a new persistent object for the SFLIGHT table. Then we will look at the Persistent Data Mapper. Finally I have three example exercise programs that I will share.

Creating the Persistent Object Class
We start off with the task of creating a Persistent Object Class. The process is very similar to creating any other type of global class in ABAP Objects. From the create class dialog, you simply choose Persistent Class for the Class Type.

image

After the class creation, if you look at the Properties tab you should see something like the following:

image

You will notice that even though I choose Public as my instantiation type in the create dialog, SAP has forced this to Protected and locked the field against update. That is because more than just this one class was created. You also have generated two additional classes. A ZCB_ class that is your Base Class and a ZCA_ class that is your Agent Class.

image

You will also see that your main class you just created now also has a Friends relationship to the Base class. The Base Class in turn is the Superclass for the Agent Class. Later when we get to the coding part of this exercise you will see that we always use the Agent class to create instances of our persistent class.

image

Right now our persistent class has just 5 methods that it has inherited from the IF_OS_STATE interface. You are not allowed to alter the GET or SET methods because the internal coding is generated. However according to the documentation you can change the default code in the HANDLE_EXCEPTION, INIT, and INVALIDATE methods. For the purposes of this exercise, we will just leave the default coding.

image

Persistent Data Mapper
Well we have a persistent object, but it doesn’t do much yet because we haven’t mapped any data objects to the class. This is where the Persistent Data Mapper comes into play. On the Main menu bar in the class builder, we have an extra button when we are working with our persistent class. This button will navigate us to the Persistent Data Mapper.

image

When we first enter the Data Mapper we are asked to add a Table or Structure. For this example we will enter SFLIGHT (Please note that to get all of my screen shots I had to create my Persistent class multiple times. That is why in some of the screen shots you might see a slightly different class name).

image

Now at the top of the screen you see an area with your persistent class and all of its attributes (there are none yet). At the bottom of the screen you see all the possible fields exposed by the data object we selected.

image

If you double click on a field from the Table/Field View, it will be loaded into the middle part of the editor. From this area you can change the attribute name, description, visibility (Public, Protected, Private), and read only flag. Once you are complete you can press the arrow button to the left of the attribute name to add or update this attribute in our persistent class.

image

You can then repeat this task for each field we want to expose as an attribute in our Persistent Class. You also have a context menu that can be used to alter the attribute once it has been added to the persistent class.

image

When we save and exit from the Data Mapper, you should see many new SET_ and GET_ methods that have been generated in your Persistent Class.

image

Coding Examples using our Persistent Class
We have our Persistent Class and all the data fields mapped and exposed. All that is left now is to start writing some code to use our persistent class. For our first example, we will start simple and just read some data from out persistent class. You can see that we use the Agent class to create the instance of our persistent class. You can also see how you can use the get methods in calculations instead of the actual attributes. Finally we will book an additional person and increase our seats occupied. We then refresh our persistent object to prove that we have updated the database.

For the second example, we are going to get a little fancier. We are going to get an internal table full of instances of our persistent class. My internal table isflight contains just our data keys, along with the persistent class instance (my_flight) which contains the rest of our data. We then write out a simple report:

The final example is very similar to the first one. The only difference now is that we are going to use transactional object services to commit our changes through our persistent class. As you can see you can write an event handler for the completion of the update. It is in this event handler that we will reread the data to prove that the update was successful.

Closing
Admittedly these have been rather simplistic examples. Hopefully thought, they give people a chance to see that persistent objects do exist and give some simple steps to get started using them. These examples do not really show off the power and benefits of using persistent classes. Once you have down the basics of creating and working with persistent objects, you will be ready to explore their greater possibilities.

To report this post you need to login first.

67 Comments

You must be Logged on to comment or reply to a post.

  1. Subramanian Venkateswaran
    Just yesterday, I was questioning about persistence classes to my colleague and today I have got the best information. Thanks a million, Thomas.

    Moral of story: Put question in SDN, chances are, you might get a much better answer or lucky, a weblog

    (0) 
  2. Peter Inotai
    Hi Thomas,

    Thanks for the great weblog!

    I have a couple of questions:
    – Do you have also a kind of real life example of persistent class?

    For example a typical ABAP report, where the data is picked up from 10-15 tables.
    Would it be easier to implement it with persistent classes? I think the code would be more complicated, difficult to overview:-(

    – Do you have experience about performance?
    Are Persistent Classes better from performance point of view?

    – Do you know if every kind of table can be used (eg cluster), or only transparent table? I couldn’t find any info about this.

    I’m still on 46C, having MiniWAS 6.20, played around a little bit of persistent class, however it’s still not clear in which situation I should use it.
    /BTW persistent classes are available in 46C (eg CL_SBOOK_PPF), but they are not released for customers./

    Thanks in advance,
    Peter

    (0) 
    1. Thomas Jung
      1.  Yes I have some real life examples.  My biggest and best example is an Issue tracking system I build in SAP.  It has about 15 tables.  All the data access in this system is done via Persistent Classes.  I actually roll all of my Persistent Classes together into a Data Model Class.  The end applications don’t even realize they are working with Persistent objects, because the data model class takes care of those details.  I described the overall application (although I didn’t dive into the details on the Persistent objects) in the BSP in Action: Kimball International.

      2. I would think that generating persistent objects just to write a report might be overkill.  However when persistent objects are used together with a larger data object class (that might already include complicated selection and calculation logic), this can save time.  I do plan to create persistent objects for new development (custom tables and transactions) as I go forward. This then makes reporting for these new systems easier.

      3.  I’m sure at a very low level performance isn’t as good.  You have the overhead of the OO layers and the persistent logic.  Basicially this is just like any other layer of abstraction that you apply in programming, low level performance deceases.  Now the real question is: Is that performance noticable.  No it isnt’.  I’ve used persistent objects as part of a data load (large amounts of data being loaded into Z-Tables through the persistent classes).  The performance was quite good – I loaded thousands of records in a few seconds.

      4.  I have hit some limitations.  I couldn’t directly generate a persistent class for tables that contained variable size strings or binary strings.  That is the data mapper wouldn’t work directly against these tables.  There might be a coding work around, but I haven’t ever gone back and spent a lot of time on this.  I would imagine that Pool/Cluster tables might be a problem as well, but I haven’t tried that yet.

      (0) 
      1. Thomas Jung
        I know this is an old posting, but I was reading back through my comments:
        >I couldn’t directly generate a persistent class for tables that contained variable size strings or binary strings.<<br/>
        The other day I was generating a persistent object on 640 and I tried this again. No Problem! So in 640 the limitation on strings seems to have been removed.
        (0) 
      2. Andy Cliff
        Hi Thomas,

        I have recently had a little spare time to investigate persistent classes again and have found a problem with using reference attributes.  Did you define any reference attributes in any of your persistent classes?  I.e. did any of the DB tables you created contain references to other persistent objects? 

        I have created two tables, one consists of a business key and could almost be considered an index table to another table which contains the data.  The business key table also contains an instance GUID and a class GUID as specified in the SAP help in order to store a reference attribute to another object:

        http://help.sap.com/saphelp_erp2005vp/helpdata/en/06/f23c33638d11d4966d00a0c94260a5/frameset.htm

        The data table contains one key field which is a GUID.  I can create an object for the data table, I can then pass this object into a business key object and these entries will both be written to the database.  However, when I read an object back from the mapping table the reference atribute of the data table is blank.  The reference object has the correct type but it’s attributes are not populated.

        Regards,

        Steve.

        (0) 
        1. Thomas Jung Post author
          I have never used the functionality you mention.  As I described before my preference is to use business keys and multiple persistent objects all tied together by a higher level class.

          But I am familiar with what you describe and it does sound like it should be working.  Perhaps you have just encountered a bug?

          (0) 
          1. Andy Cliff
            Morning Thomas,

            It’s a shame that this functionalilty doesn’t seem to work since reference attributes are very powerful.  If you are working with complex data schema across many tables then reading the high level persistent object would in turn read all the subordinate reference attributes without you having to do any additional programming.  This could reduce the amount of code required in the data model class.

            I’ll raise an OSS message to try and find out if the behaviour I’m seeing is the expected behaviour.  I’ve tested reference attributes on a 2004 and 2004s SR1 system and they both behave in the same way.

            Regards,

            Steve.

            (0) 
            1. Andy Cliff
              I hadn’t set up a foreign key relationship between the business key table and the data table yesterday.  I just created a relationship and regenerated the classes but it made no difference.  The attributes of the reference attribute are still not populated.

              The problem seems to be with method MAP_SET_ATTRIBUTES IN the CB_persistent class.  The table field attributes are mapped and the reference attribute object is created but the reference attribute data is not read from the DB.

              I have raised an OSS message describing the problem, I hope a friendly support person reads the emessage. 🙂

              Steve.

              (0) 
              1. Andy Cliff
                I’ve found that if I create an object of the data model class before I create an object of the relevant business key class then the business key reference attribute of the data object will be populated correctly.  This is because the persistency model will always return a reference to an already existing object if you try and read the same object twice.

                This shows that the persistency implementation almost works.  It just needs the system to read related reference attributes from the DB on it’s own. 

                (0) 
              2. Thomas Jung Post author
                I agree that this functionality of persistent objects would be valuable you have encouraged me to give a try.  Hopefully you will get your answer from OSS, but now I might wait to give it a try until you get your fix. 😉
                (0) 
          2. Steve Higton
            I’ve found that this is not a bug.  The attributes of reference attributes are loaded on demand.  So, although the attributes of reference attributes are blank when the main persistent object is loaded the attributes of the reference attributes will be populated when their relevant GET_… method is called.

            (0) 
      3. Andy Cliff
        Hello again,

        In the issue tracking system that you created, how did you implement access to rows of tables that had an item relationship to a header table?  The GET_PERSISTENT method retrieves a single row, and if you need to read a whole “document” you need to read a “header” row and multiple “item” rows.  Did you use queries to access the item rows or did you SELECT the item keys from the DB and then use the GET_PERSISTENT method for those keys?

        Regards,

        Steve.

        (0) 
        1. Thomas Jung Post author
          Well when I wrote that original system it was back on 6.20 so yes I did have to “cheat” and still use SQL to get the multiple instances of the item persistent objects.

          However today with 04s you wouldn’t have to do that.  The persistent system has a query manager (if_os_query_manager) and query object (if_os_query).

          You could do something like this:

          agent = zca_item_pers=>agent.
          query_manager = cl_os_system=>get_query_manager( ).
          query = query_manager->create_query(
             i_filter = `HEADER_ID = PAR1` ).

          item_objects = agent->if_os_ca_persistency~get_persistent_by_query(
             i_query = query
             i_par1  = header_id ).

          (0) 
            1. Thomas Jung Post author
              1. Query service not working against protect and private attributes makes since because the query class wouldn’t have visibility to those.
              3-5. The regeneration problem would seem to be a bug perhaps.  You should enter a support tick and describe the situation in detail.
              (0) 
            2. Thomas Koll
              1. Query service does not work if attributes visibility is different from public (privat or protected).

              I tried to declare friendship to make a private attribute visible to the query but it didn’t work. I tried the following entries in the friends declaration of my class ZCL_.. :

              IF_OS_QUERY_FACTORY
              IF_OS_QUERY_EXPR_FACTORY
              IF_OS_QRY_SERVICE
              if_os_query
              if_os_ca_persistency
              CL_OS_SYSTEM
              CL_OS_QUERY
              ZCL_..

              Always the same exception. The private attribute is not visible to the query. Does anyone have a solution? I changend the visibility to public just to have a workaround but this is not a good solution (it forces change of visivbility just because of the query manager as part of abap objects services). All in all i have no solution under NW 7.0.

              (0) 
  3. Scott Barden
    Hi Thomas,

    Another good weblog.  And in addition to persistent classes, I liked seeing the new message syntax “DISPLAY LIKE”, which I hadn’t come across before (still mostly on 4.6).

    Have you used persistent classes to map 1:N or N:M relationships?  Like a purchase order and its items?  Can you load an order and automatically have the items accessed on demand?

    Cheers,
    Scott

    (0) 
    1. Thomas Jung
      I guess my answer to this question is yes and no.  I haven’t done this directly in a single Persistent Class.  What I did is generated multiple Persistent Classes (one for header and one for items-Acutally I had 4 levels-Header, Item, SubItems, SubItems Text).  I then wrote a data model class that combines these together.  To my application objects, they simply request a single logical unit.  The data model class then goes and retrieves the header and all associated items/subitems via the multiple persistent classes.  There might be a way to do this in the persistent objects themselves. However I was already building a data model class (with locking, change object, and update logic), so it seemed logical to structure the classes this way.
      (0) 
      1. Steve Higton
        Hello Thomas,

        What do you mean by a “data model class”?  Do you mean that you created a standard class (class type 0; general object type) and added attributes to this class that are defined with reference to the persistent classes?

        I have created a thread at Creating Persistent Class to Access Multiple Tables in which I described a contrived example with one header and one item table and the problem I had when creating a persistent class that included both the header and the item table.  I would be very grateful if you could read the posts I made to the thread and comment on them (if you have time amongst all the other things you have on your to-do list!)

        After some experimentation I would like to work out a design pattern that I can apply to data schemas so that I can use persistent classes in any further developments I work on.  I appreciate that this may be overkill for simple reporting requirements though.

        (0) 
        1. Thomas Jung Post author
          By Data Model Class I do just mean a standard class. There is no special support in the workbench for this type of object – it is just a logical construct.

          I always generate my persistent classes as a one-to-one relationship to my database tables. Order Header – VBAK – ZCL_PERS_VBAK and Order Items -VBAP – ZCL_PERS_VBAP for instance. I then create what I call a data model class – ZCL_SALES_ORDER. This class would have methods like GET_HEADER, GET_ITEMS and perhaps even GET_ORDER which would contain exporting parameters for both the header and items.  Inside this data class is all the logic to interact with the persistent object.  Outside application classes only ever have to deal with the data model class – it would also include all the locking logic for instance in an update transaction. 

          In one example, I had a large custom system. It had about 20 database tables.  Each table had its own persistent object.  However I only created one data model class.  That data model class was then used in one Base (Abstract) Application class.  That Base Application Class was then used as the Application Model for two different UI implementations (SAPGui and BSP).  The Base Abstract Application class had basic application logic that was shared by both UI versions.  The more specific implementation application classes had logic specific to the UI technology being used (One was actually a BSP Model Class – inheriting from CL_BSP_MODEL2 and the other had logic structured to PBO/PAI for SAPGui). 

          (0) 
    1. Thomas Jung Post author
      Personally I generate a persistent class any time I create a custom table. The only exception is if the custom table is going to be used for customizing entries.  In this case I will generate Table Maintenance for the table – so I will never have custom logic that updates the entries.

      Otherwise I try to take all access (read, update, delete, create) for any custom table through a persistent object.

      (0) 
  4. Brad Walker
    Thomas,

    I can’t seem to find your blog on the Issue Tracking system you wrote using Persitant objects wrapped with a Business Class.  Can you post the link.  The one on this blog takes me to a home page.

    (0) 
  5. Brad Walker
    I’m needing to convert a table of persisted objects to a table of type [database table] of which the persistant object was created.  Does this mean I have to literially loop through each field assigning to a fields of type [database table]?  If, so this seems to be a limitation since in many cases like in a bapi, you can’t return the more complex type persistant objects.

    Any thoughts on this.

    (0) 
    1. Thomas Jung Post author

      >Does this mean I have to literially loop through each field assigning to a fields of type ? <br/><br/>Yes this is what it means.  However it doesn’t have to be difficult or even something you write for each object.  I created one generic, utility class method that uses the RTTS to dynamically do this casting for me:<br/><br/>METHOD get_structure_content.<br/>@78\QImporting@  IR_ENTRY  TYPE REF TO OBJECT  Reference to one table line<br/>@78\QImporting@  IT_COMPONENT  TYPE ABAP_COMPDESCR_TAB OPTIONAL  List of structure components<br/>@79\QExporting@  ES_RESULT TYPE ANY  Result structure with data<br/><br/> DATA DECLARATION<br/>***********************************************************************<br/>  DATA: lt_component LIKE it_component.<br/>  DATA: lr_struct_descr TYPE REF TO cl_abap_structdescr.<br/>  DATA: lv_method_name TYPE string.<br/><br/>  FIELD-SYMBOLS: <ls_component> LIKE LINE OF it_component,<br/>                 <lv_value>     TYPE ANY.<br/><br/> PROGRAM<br/>***********************************************************************<br/>  IF it_component[] IS INITIAL.<br/> get result type info<br/>* –


      * –


      ENDMETHOD.

      (0) 
  6. Harish Kumar Kalla
    Hi Thomas,

    First of all I should Thank You for posting the blogs which can help anyone from the novice to an expert, if he has any doubts.

    I am new to ABAP Persistent Objects. I read your article and I tried to implement the same.

    But while compliling it, I am encountering an error for the below mentioned code:

        my_flight = ZCA_KHK_PERSISTENT=>agent->get_persistent(
           i_carrid = p_carrid
           i_connid = p_connid
           i_fldate = p_fldate ).

    ERROR: Field AGENT is Unknown.

    Can you please let me know where the problem is.

    Thanks,
    Harish Kalla

    (0) 
    1. Thomas Jung Post author
      I’ve given this workshop where the first exercise is to create a persistent object to about 1000 people now.  Out of those thousand 5 have had the problem you describe.  I have no idea why it happens, but in a very small percentage of the time the generated relationship between the agent and the persistent object just doesn’t create right.  The only solution I know of is to delete all the objects and start over.  In all the workshop instances, the second time things worked just fine.
      (0) 
      1. Harish Kumar Kalla
        Hi Thomas,

        Hey this is really bad …. as you told me to delete all the existing classes, and to try again…. I did the same and now its working fine.
        But why this should happen like this….

        I really liked the Object Services. Anyways, I need your help. Presently I am working on BAPI’s and Enhancements but I want to learn Persistent Objects and WebDynpro.

        Can you please tell me about the book that you and Rich had written (Nxt Gen ABAP Dev), has examples with code…. so that i can purchase it and learn the new technologies

        Thanks,
        Harish

        (0) 
        1. Thomas Jung Post author
          >Can you please tell me about the book that you and Rich had written (Nxt Gen ABAP Dev), has examples with code…. so that i can purchase it and learn the new technologies

          Well that is the purpose of the book – it focuses on the new technologies and techniques in ABAP through one integrated example application that runs through the book.  It also contains a CD with the source code in Text Files/Screen Shots, SAPlink or as a Transport File.

          (0) 
  7. Marcus Schug
    Hi,

    I tried out the example an have some questions:

    1. When I should use Persistent Classes.
    2. Is there a possibility to enqueue the corresponding database entry when I call the method ->get_persistant( )
    3. Is it possible to create a global setter which has an importing parameter like the sflight. In the generated code I must set each attribut.

    Greetings Marcus

    (0) 
    1. Thomas Jung Post author
      1. Generally persistent objects can be used as a replacement for SQL.  However there would be some general recommendations.  First Query services don’t support select-options, so if needed you will still have to use SQL.  Also there is overhead with the persistent object that you don’t have SQL.  So generally SQL is still best suited for create reports where a large number of rows are being read.  However for single instances of a business object – display, update, and creation – like the major ERP transactions (MM01, VA01, etc); persistent objects would be the perfered choice.  Ideally you would wrap your persistent objects in some sort of business object or model class layer that has the extended business logic in it.  Then you would probably service enable that model class – all before you use it in a UI.  That gives you the maximum flexibility and reuse over time.

      2. Enqueue hasn’t changed.  You still must call the generated Enqueue function modules. This is generally done at the Business Object or Model Class layer.

      3. Yes.  Look at the TechEd 2007 materials for CD251. We used the RTTS and Dynamic Method Calls to write just a such a generic method that does all the set and get methods based upon a structure.

      (0) 
  8. Gaurav Fadnis
    Hi Thomas,

    This blog is very helpful for understanding and implementing PERSISTENT CALSS. Thanks for sharing.
    I have one querry about the set methods. When we map the fields ofthe table in the field mapper the respective SET_ and GET_ methods are created automatically.

    When mapping a key field for the same purpose only GET_ method is created and not the SET_.

    Create_persistent can be used to create object with key fields but there is not method created for SET_* for key fields.
    Ofcourse we can write one ourself but want to know if there is any setting which is prohibiting this being generated automatically.

    Regds,

    Gaurav

    (0) 
    1. Thomas Jung Post author
      Key fields get set via importing parameters of the create_persistent method.  Once set, they should not be changed therefore there is no SET method.
      (0) 
  9. J.W.F. Kaagman
    Although this is an old blog, it is still very usefull. Excellent article.
    However, I was playing around with some classes, and I got the need for creating an object for which I need to maintain a history – for example similar to any infotype in HR. Do you know if SAP is planning to extend persistent classes with this functionality?
    What would you suggest for an implementation? I did create some additional methods which took care of validity periods of the object. I placed them in the ZCL-class, but I am not completely happy with this solution. Any comment would be appreciated.
    (0) 
    1. Thomas Jung Post author
      To me the maintenance of validity is not an operation that should be done at the persistent object level – that is application logic and should appear in a higher level class.  The Persistent object should pretty much be a direct representaiton of the underlying database structures.  I would recommend the approach that you took that this sort of thing should be covered by application logic – perferably in a business object class.  What exactly where you looking for?
      (0) 
      1. J.W.F. Kaagman
        Hello Thomas,

        Thank you for your reply. Reading your answer I have to agree with you on one point: Maintaining the validity of an object should be done in the application logic of the corresponding business class.
        However, I disagree that the Persistent object should pretty much be a direct representaiton of the underlying database – I love it that with persistent classes you can hide the actual database representation & operation – You can even add some additional tables for performance the developers don’t ahve to care about anymore.

        What I was looking for is the right place to maintain the validity periods for a time-dependant class. I have created some additional classes in the business-class (the ZCL_-class) that in their turn call on the ZCA-persistance methods. But somehow this solution seems a bit awkward to me – Now there are methods for persistancy in two classes – both in the Persistent Agent class (ZCA- class) and the business object class (ZCL), in which only the latter methods maintain the validity correctly.

        And besides, I was hoping that SAP was thinking about a specialization of the persistence class for the special cases of time-dependent objects.

        (0) 
        1. Thomas Jung Post author
          >But somehow this solution seems a bit awkward to me
          Not right or wrong answer here.  However this is why I like two layers.  For very large projects I like to use the Persistent Object as a 1:1 match to the DB.  I then create a business object class that maps to the logical structure of the business object.  This is where I would typically put the time dependent logic as well as other things. 

          Ideally the persistent objects would not be visible outside their home package and only the business object class would be.  This business object class would then be used as within an application specific classes (Enterprise Server Proxy Classes or Web Dynpro Model Classes).

          However this is just one of several approaches you could take.  The core idea – however you go about – is to achieve the main point you make – performance or feature optimization that is reusable and provided without the application developer having to care about it.

          On your specific question about the specializatoin of persistent classes – I don’t see anything like that coming.  Instead I think you will see more tools to help you build at the Business Object Class or Enterprise Service Server Proxy class layer.

          (0) 
    1. Thomas Jung Post author
      Technically you can, but I would be cautious about doing so.  The GET/SET methods are generated and if you add code to them and then regenerate the persistent object your coding will be lost. 

      It might be better to instead wrap the persistent object with a higher level object and put the logic you need in there and keep your persistent object at its generated state.

      (0) 
      1. Marcus Schug
        I have create a work around by making all attributes private and creating a dynamic set Method, which calls special methods for attributes.
        (0) 
  10. Marcus Schug
    Hi,

    1. Is it possible to create change documents automaticly with a persistent class?
    2. I used the following code:
    CONSTANTS lc_query_method_name TYPE string
        VALUE ‘IF_OS_CA_PERSISTENCY~GET_PERSISTENT_BY_QUERY’.   “#EC NOTEXT
      lr_query_mng = cl_os_system=>get_query_manager( ).
      lr_query = lr_query_mng->create_query(
        i_filter = ‘BUKRS = PAR1 AND PARTNR = PAR2 AND GJAHR = PAR3’ ).
      TRY.
          CALL METHOD yca_test=>agent->(lc_query_method_name)
            EXPORTING
              i_query = lr_query
              i_par1  = lv_bukrs
              i_par2  = lv_partner
              i_par3  = lv_gjahr
            RECEIVING
              result  = lt_entry.
        CATCH cx_os_object_not_found cx_os_query_error.      “#EC NOHANDLER

      ENDTRY.
    It works fine.

    Is a query like the following also possible?
      lr_query = lr_query_mng->create_query(
        i_filter = ‘BUKRS = PAR1 AND PARTNR IN PAR2 AND GJAHR = PAR3’ ).
    When I have a range of Partnr. And what could I do, if I have more parameters?

    Best regards

    Marcus

    (0) 
    1. Thomas Jung Post author
      1. There is nothing build into persistent object for creating change documents.  You could do it the same way it has always been done.  Keep a before and after update copy of your data in internal tables.  Call the generated change object function module passing in this data.

      2.  The query functionality does have some limitations as you found.  You can’t use ranges.  This is where I usually fall back to regular SQL (nicely encapsulated in a class).  I try to only retrieve the keys I need and then use the keys to retrieve the persistent object instances.

      Remember though that persistent objects come with some overhead.  The overhead is very minor when you are only working with one business object instance.  However if you are building a report with thousands+ records that overhead begins to add up. 

      (0) 
  11. Marcus Schug
    Hi,
    in the generated method header of the method is written:

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

    Is it really true?

    Greetings Marcus

    (0) 
    1. Thomas Jung Post author
      When you create a persistent object via the create transient, you are still connected to the persistent services.  When you create transient, the key must only be unique in memory.  However as soon as you issue a commit work, the transient object is converted to persistent and an attempt is made to write it into the database.  This is where you encounter the failure via express mail.  What is the use case you are trying to accomplish?
      (0) 
      1. Christian Assig
        Hi Thomas,

        I really like your article and share most of your opinions on use cases for persistent objects.

        However, what you said regarding transient objects is not entirely true. The Persistence Service never writes transient objects to the database. A transient object only exists in your internal session.

        The Persistence Service makes sure that you don’t use a transient object and a persistent object with the same key, or two transient objects with the same key.

        If you want to write a transient object to the database, the only way I know is to RELEASE the transient object and create a persistent one. Only a persistent object will be written to the database when you issue COMMIT WORK or end() on your top-level transaction. (help.sap.com says you cannot use RELEASE on transient objects, but at least in our AS ABAP 7.0, you can.)

        Best regards,
        Christian

        (0) 
  12. Richard Gu
    Thanks for your article about ABAP OO Persistence. I always associate ABAP OO Persistence with JAVA Serialization. Thus can not make me understand ABAP Persistence. Thank you again for giving me the right way.
    I still have a question:
    If my class is a complex class (eg, have a member that refer to anther class object), can we/how to persist it?
    (0) 
    1. Thomas Jung Post author
      I think you are still mixing persistence with serialization.  The structure of the ABAP Persistent object will generally match the underlying database table.  Therefore it won’t necessarily have a complex structure.  It is possible to do this however by nesting persistent objects within each other.  We did this very thing in the exercises of the TechEd session CD251 from last year.

      Now if you just want to “persist” a normal object instance – you can do that serialization to XML and storing the XML.  You can serialize an object that references as attributes to other class.  The only restriction is that the inner class reference must be public and also have the Serializable interface.  Otherwise they are ignored during serialization.

      (0) 
      1. Richard Gu
        Thanks. So what’s my understand is – ABAP persitence approximately equals to Hibernate in Java and ABAP still have serialization function. Is it right? BTW, where can I find some reading materials about ABAP serialization? For example, the XML Serialization you mentioned. Thank you indeed~ 
        (0) 
        1. Thomas Jung Post author
          This very blog you are reading has a section at the beginning about XML Serialization. Perhaps it was my combination of the two topics that even lead to some confusion.  I was only covering them both here because it was a response to a survey I say that listed that neither technology existed in ABAP.

          There really isn’t all that much to tell.  You can also look at the key word documentation for call transformation. You can also read up in the online help about simple transformations and XSLT.

          (0) 
  13. René van Mil
    I wish I read this blog a couple years ago, very informative. I’ve been using this in a nearly-fully-object-oriented web dynpro application I’m working on and thought I’d share some things I noticed so far:

    – If you’re going to use this in an object oriented application which uses several classes, which in their turn start and end transactions, you’ll want to check cl_os_system=>init_state before calling the cl_os_system=>init_and_set_modes method. It only allows you to set it once for each session (correct me if I’m wrong).

    – You can use the get_current_transaction and get_top_transaction methods from the transaction_manager object when you want to check if at that point you’re already inside an existing transaction (so you can combine multiple tasks in one transaction).

    – Design things first (obviously ;)), it’s easy to get lost in started/ended/top/sub transactions.

    (0) 
  14. Swapnil Kulkarni
    Hi Thomas,
    This was perfect introduction to persistence services, Thanks a lot.

    I am using them in WD-A application, however this application starts and transfers some parameters to workflow also modifying the db table using persistence service.  Later workflow independently modifies the table; hence a lock is placed on table. But I am not sure how to use lock concept here. Should I call enqueue method just like it is called before writing SQL? And after I read/write (get/set) data from the persistence object the dequeue method?

    By the way, new posts (7.01,7.02) on abap here on sdn and egeeks are really good. Also I am amazed to hear and in fact waiting to see abap in NWDS (can you please confirm this?). I will be able to do WD-J WD-A at the same place then!

    (0) 
    1. Thomas Jung Post author
      The use of persistent objects doesn’t change the way you perform locking.  Locking is done outside the persistent object and should follow the transactionality approach you are using in your applications. If your application is the typical long lifetime transaction (lock at start or choice of change mode and carry to the end of the application) you might have the dequeue in some screen change (navigation plug maybe).

      >Also I am amazed to hear and in fact waiting to see abap in NWDS (can you please confirm this?).

      I can’t really comment on ABAP in Eclipse much. I can tell you to check out TechEd Session CD106 this year to get the latest news on that subject.
      http://www.sapteched.com/usa/edu_sessions/session.htm?id=131

      (0) 
      1. Swapnil Kulkarni
        Thanks!

        I am calling enqueue FM just before I update (set) the data by persistent object and releasing lock by calling dequeue FM at navigation change (after successful update to db).

        Thanks for link, I will look forward to attend it. It seems its in labs as eclipse plugin module and not NWDS for GA.

        Best regards,
        Swapnil

        (0) 
  15. Vicente Ángel Lopez Romero
    Hi Thomas,

    First of all, thanks for that useful introduction to abap persistence objects.

    This link has been stored in my favorites folder  pending to be read for some years, and finally… I managed to get some time to make a try!

    I understood from your comments that all business logic should be modeled in some other class(es) in order to maintain 1-1 between DB table and Pers. Classes, but I am not completely sure about how to deal with the inheritance.

    I would say that I should model a Relational DB layer on one hand and business logic OO layer on the other hand. Therefore, taking into account the just said 1-1 rel, inheritance should not be a problem because basically I will be creating Persistence classes to get an abstraction for the relational DB access, and inheritance is not a “valid” concept in this relational context.

    Please let me know if I’m wrong

    Thanks in advance
    BR
    Vicente

    (0) 
    1. Thomas Jung Post author
      >>taking into account the just said 1-1 rel, inheritance should not be a problem because basically I will be creating Persistence classes to get an abstraction for the relational DB access, and inheritance is not a “valid” concept in this relational context.

      I would say that is a pretty good explanation of how I would personally do it.  The persistent objects would be difficult technically to use inheritance on anyway becuase of the Base and Actor classes. Any inheritance I generally build in at the business object layer above the persistent objects.

      (0) 
    1. Thomas Jung Post author

      Yes many older blogs on SCN lost their formatting when SCN went through the platform change a while back.There is no easy fix other than to manually correct at some considerable effort; which I’m afraid I don’t have time to do for blogs that are 9-10 years old. Sorry.

      (0) 
  16. Rafael Guares Quadros

    Hi, Thomas.

     

    Regarding the ABAP persistence layer, do you happen to know wheather there is any way of setting a maximum number of records for query result?

     

    Thank you,

    Rafael Quadros

    (0) 

Leave a Reply