0

I have been thinking about a design problem and possible solutions in my own. I am pretty sure I am not the first one to have noticed it, but I cannot google for it since I do not know the standard naming of the different participants.

It is NOT the state pattern.

My problem is that, when dealing with ORM, I often end with something like that

Employee 
-------- 
Id       
Name     
Surname
BirthDate
DefunctionDate

And using an Object Relation-Mapping (in my case JPA), I end with two entities, Employee and Contract.

Now, most of the fields of Employee are just "intranscendent"(*1). It really does not affect the application if the Employee's name changes from 'John' to 'Mike'. As long as I put some validation for the input fields. But if, say, defunctionDate changes from null to some date, some logic must be executed (for instance, closing the current contracts, revoking system access, etc.). I would call those terms "transcendent"(*1).

The first step would be add an specific operation which sets such field setDefunctionDate and handles such logic, and I am ok with that. The problem that appears is how to ensure that the fields are not updated when updating "cargo" data.

I see three "easy" options:

  1. Ignore changes in a bean: If I have an update(Employee employee) method, then each time the method is executed I should retrieve the object from DB and set the "transcendent" field(defunctionDate) of the incoming object with the value from the object stored in the DB. That "retrieve the object from DB" means one or several extra accesses to DB, which are not a good thing. Also, this has issues when there is cascading of the changes.

  2. "Observer" pattern: Like 1., but in this case a modification is found in a "trascendental" change a listener that handles the extra logic is fired.

  3. Another possible solution is having a method for each field in the entity, but I think this will usually be too verbose, and will break the purpose of having an ORM.

Of the previous options, I thing 2) would be the best, but I still do not like the fact of the extra DB accesses even when no trascendent field has been changed.

The only solution I can think of would be moving those "trascendental" fields to a separate entity, which would be in a one-to-one relationship with the original entity. Something like

Employee
--------
Id                   Employee_Trascendent
Name       --------> ---------
Surname              Employee_Id
BirthDate            DefunctionDate

The API would only allow direct modification of the Employee entity, and DefunctionDate would only be modified by an specific API method.

That said, I find my solution a bit overcomplicated and, since I cannot see any reference to anything similar, I think that maybe I am missing some more obvious solution.

I would like your help to determine the correct terms to search ideas for and, if why I propose has a name, its name.

*1: If you know a better term please tell me it, remember I do not know the proper terminology.

  • Help me understand, you have fields that affect the entity's functionality in the program and then you have fields that don't (name, surname, birth date). The fields you set are arbitrary. If you don't wish to update certain fields, don't. I'm not sure I understand where the problem lies. – Neil Nov 17 '14 at 9:46
  • @Neil, thanks for your help. Using an ORM (JPA), I will usually persist/update/retrieve whole objects/entities; I will not create an SQL query like "UPDATE Employee SET Name=?". Also, entities may be persisted indirectly (by using cascading). – SJuan76 Nov 17 '14 at 9:54
  • Though it matters not if the entity is updated. What's important is that should certain changes be made to certain fields, you perform additional operations, is that correct? – Neil Nov 17 '14 at 9:55
  • @Neil That is an option (covered in point 2). While it looks like the most "canonical" option, I do not like the extra DB accesses. Another option (which I would prefer) would be having an API update method that allows changing all of the "intrascendent" fields, and specific methods (like setDeceasedDate(employeeId, date) for changing "transcendent" fields. But the only way of translating such an API into ORM/JPA I can think of is my last proposal, and as I said I feel I might be overlooking some other solution – SJuan76 Nov 17 '14 at 10:17
  • You shouldn't have to worry about performing extra DB accesses, aside from the fact that if you separated it into two separate entities with 1-to-1 relationship, you'd still perform the same number of transactions. – Neil Nov 17 '14 at 11:07
1

As I see it, the ORM doesn't create the side effects, your code does. If you ask an ORM to save an entity, it does so, without performing additional operations, or should there be a database trigger of some sort, in my personal opinion you should remove it in favor of having more control in your program.

As such, don't worry about saving your entity multiple times (perhaps once in creation of an Employee once you know first name, last name, birth date, etc., then later in a later step). If your program handles input of this information in multiple steps, then it should be saving as you go along. The stress that you put on the database is only slightly more than it would be otherwise, and look what you gain in exchange: stability and simplicity. These are two commodities worth far more than performance and I would choose to have a stable and simple program with a slight performance hit over a fast instable and complicated program any day of the week.

I suggest that you use option 4. You have one dbo section in your program that performs the actual duty of saving an Employee. It gets accessed from different areas of your program, namely when you need to update information on an Employee that won't create side effects, and when you need to update information on an Employee that will create side effects. In the latter case, you should perform all side effects in a transaction such that should the side effects or actual save of Employee fail, nothing is done.

The dbo should only provide the means to perform the save in its own transaction or as part of another transaction, but it should not know what side effects result from saving Employee.

I hope that answers your question.

  • Thanks for the feedback. Still I will let the question remain open for a few days; while I feel my option (number 4) is correct I would expect many people to have had the same issue, and I would like to know if the pattern has been identified / named (principally because there I will be able to study possible issues that I am missing) – SJuan76 Nov 17 '14 at 15:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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