I need to implement a rollback system and the memento pattern gets mentioned regularly as a solution to this requirement, but in all cases a single object is used and it works in memory, persistence is never discussed.

But what if I need to store the memento/state in a database? What if multiple objects are involved?

For instance, a user makes some changes affecting multiple tables. Here many rows and tables are involved, but we could say everything can be followed back to a single user instance. How can I adapt the memento pattern to

  • save the state of multiple (related) objects instead of a single one?

  • save the memento in the database, associate it with the user and create a state history system?

  • Hmm, I think you're confusing some concepts. Memento pattern is something you would use in-program to organize states. Persisting data to a database is not using memento pattern. It's simply saving the data. You would use a transaction to guarantee atomicity of the operation. Maybe I don't quite understand what you need to do. Can you give an example? – Neil Oct 9 at 11:00
  • @Neil Well but I need to save the state (which is held by the memento object) to the database. My example is a tournament instance having scheduled games (at a certain date, time, place... more information inter related). I need to be able to save the schedule at any given point so that if it changes in the future we can rollback to previous versions. I already implemented serialization/deserialization of a schedule (data saved in the database as a json string), but I am having trouble with the design of the actual rollback/undo system. – dabadaba Oct 9 at 11:09
  • Hmm, I see what you mean. Let me think on it and I'll write an answer shortly. – Neil Oct 9 at 11:10

So as I understand it, you're currently using a Memento pattern to hold scheduling information, and your question pertains to how you can integrate this with a database.

Well the memento object must be able to save and restore the current state of a schedule. The actual saving of the state happens when the memento is created, so my idea is that you should grab all the data as you do already, but then you immediately persist that data to the database. The data can expand multiple tables, but have a parent table to deal with a memento instance to record one-to-one relationship. When you persist this instance, get its unique id that identifies that record and lets you retrieve all the data. This id then gets sent back to the memento. This means the memento now holds all the data and the id associated with it in the database, right?

Use the memento as you would normally. It has all the data already present and you should be able to continue using it normally throughout your program.

Now what about the scenario in which your program starts up and you need to restore a particular memento? You have a table with all your memento states saved! Grab a list of all their ids, and create a memento containing only the ids for each record.

When the data is requested for restoration, at this point, use the id to load all the information from the database. In this way, your program uses the mementos transparently. The memento state is persisted to the database, and everyone is happy. :)

You may or may not decide to hold onto the data you persisted with the memento. With this functionality, you can also choose to abandon the data in favor of holding just the id itself (so if the data is needed, you can once again retrieve it from the database). If you have the memory for it, and you think that data will be useful again, you may choose to simply hold onto the data to avoid necessarily having to load it again from the database.

I don't know what language you're using, but some languages such as Java support soft references which would be ideal here, which frees up the space in memory only if memory is required. Good luck!

  • Can you check out if I got the right idea?: pastebin.com/CvUmajSw All diagrams I see are actually missing the caretaker part. As you can see, I am creating a new memento with the persisted data so we can restore from it, which honestly doesn't make much sense... But I don't want to keep the serialized data in memory. I don't see any other way around it. Actually, I am forced to instantiate the memento object myself, otherwise a new row would be inserted in the database. I don't think this is how it is supposed to work. – dabadaba Oct 9 at 12:46
  • @dabadaba Almost. I was thinking the Memento class itself would perform the lookup and insertion. Except for the Memento class, the rest of your program wouldn't even need to know that the data were being persisted to a database. Doing it like this, you minimize impact on the program. – Neil Oct 9 at 14:17
  • yeah well, I could see the persistence part both in the memento and the originator, but given my case where I need to instantiate a memento that already existed then I need to do it in the originator – dabadaba Oct 9 at 14:36
  • By the way don't you think my caretaker kind of defeats the purpose of the entire pattern? When restoring, a database lookup is performed to get the appropriate snapshot, and then we instantiate a memento so we can pass it to originator.restore. Technically the originator doesn't need a memento object, it just needs the deserialized data... It just feels weird instantiating a memento that was already instantiated when the snapshot was created in the past. – dabadaba Oct 9 at 14:37

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.