1

There seems to be a consensus that ORMs compared to vanilla SQL/ SQL Mappers are not a good choice when dealing with existing/ legacy databases. Check out here and here for example.

I've just started using MyBatis on a business intensive application against a legacy database but due to the lack of ORM features such as change tracking I started by writing update functions in my repositories that will try to update the domain entity and its direct associations. But this made update statements significantly slow!

So we are now considering a new strategy of implementing a function for each of the following cases: updating the entity's immediate attributes (e.g.: employeesRepository.update(employee)), updating the entity's associations (e.g.: employeesRepository.updateEmployeeDepartment(employee)) or updating the entity's collections (e.g.: userRepository.updateUserRoles(user)). By following this strategy, every time you change your business logic, you need to make sure that you're persisting your changes.

The main question here is: up to what extent can you achieve persistence ignorance when using vanilla SQL or SQL Mappers such as MyBatis? Is it worth it to implement a change tracking mechanism to achieve optimized updates and clean repositories?

I would also like to know if there better strategies to map my domain model to a legacy database?

=============================

UPDATE

Why persistence ignorance? for all the good reasons. Check out: What are the benefits of Persistence Ignorance? for instance. Testability and reusability are the first things that come to mind. More about Persistence Ignorance and its benefits: msdn.microsoft.com/en-us/magazine/dd882510.aspx.

Basically my code currently looks something like this:

public assignProfessorAsDean(int academicId) 
{
    UnitOfWork uow = UnitOfWorkFactory.create();
    FacultyRepository facultyRepository = new FacultyRepository(uow);
    FacultyMember prof = facultyRepository.getById(academicId);
    /*promoteToDean updates the set roles posessed by the professor by adding a DeanRole*/
    prof.promoteToDean();
    /*now instead of saying facultyRepository.save(prof),*/
    facultyRepository.updateRoles(prof);
    uow.commit();
}

As you can see, although data access logic and business logic seem to be separate, my data access logic knows what exactly has been changed in the state of my domain objects. Say that I needed to update the prefix of the employee to "Dean" in the same promoteToDean function, then, in addtion to facultyRepository.updateRoles(prof); I will have to also add something like: facultyRepository.updateTitle(prof); etc. Yet, these are all simplistic scenarios, imagine how the code would look like for complex use cases.

http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

Community
  • 1
  • 1
Eyad
  • 327
  • 3
  • 10
  • 1
    I wouldn't exclude ORMs if what you're after is "persistence ignorance". If your database schema is sane, there's no reason you can't map it to ORM entities. If your database schema is a perfect example of bad practices and denormalization, then indeed lower-level SQL mappers are probably a better tool. – JB Nizet Nov 24 '13 at 11:19
  • What do you mean by 'legacy' database? What does your schema look like? What RDBMS are you working against? Why are you looking at 'persistence ignorance', and what problem are you attempting to avoid? – Clockwork-Muse Nov 24 '13 at 11:50
  • @jb-nizet My database is not well designed. No surrogate keys are used (keys are strings that mean something to the business and in some cases they're updatable), composite keys all over the place, no relationships. The data model of the DB is not proper (due to reasons I would not like to discuss now), this results in cases where one domain object maps to dozens of tables. As I previously said, the opinion of not using ORMs in such cases seems to be widely adopted. Check out this: http://www.summa-tech.com/blog/2011/06/07/dr-mindbender-or-how-i-learned-to-stop-worrying-and-love-hibernate – Eyad Nov 25 '13 at 08:10
  • @Eyad: I agree that, in such a situation, an ORM is probably not the best tool. – JB Nizet Nov 25 '13 at 08:15
  • @Clockwork-Muse Regarding the quality of the database, please see my previous comment. I'm using DB2 over AS/400. Why persistence ignorance? I will update my question to elaborate on this. – Eyad Nov 25 '13 at 10:45
  • Yeah, that sounds mostly problematic. Do note that composite primary keys (keys made up of more than one column that define a unique row) are perfectly viable with an ORM (if potentially a bit more involved). If the DB is going to be refactored in the future (we can hope), would it be worth it to build out views that you could query with ORM? – Clockwork-Muse Nov 25 '13 at 10:56
  • Okay, when you said 'persistence ignorance', I thought you meant "we're turning off transactions!" (see, this is why I wanted to know). Sorry, I'm afraid I won't be much help at this point. – Clockwork-Muse Nov 25 '13 at 12:11
  • Yes, the database will be refactored sometime in the future but it does not seem to be anytime soon. Abstracting the existing model with views was the first approach that we tried to adopt, but the problem was that DB2 did not have (at least proper) support for read write views that combine more than one table (using multi record format logical files) – Eyad Nov 25 '13 at 12:12

1 Answers1

1

Oh my looks like quite a pickle you're in. But never fear. There is hope. (Well hopefully 9 months later, you're not in the same situation). But for future readers.

What you want to do is have your repositories and unit of work provide a surrogate for your domain objects. The surrogate would have the persistence logic that you don't want to sully your objects with like change tracking and the like. Then when you call uow.commit() it would just inspect changes on the object and execute the appropriate sql as necessary. (It's somewhat close to what a normal ORM solution would provide.

On that note, are you certain that O/RM is not the best path for you? I know you mentioned there are no surrogate keys and stuff like that, but as long as there ARE keys and they are guaranteed unique, you can still work with it. For instance, Entity Framework (which DB2 supports) can use the Fluent Mappings to map the non-standard keys to your domain object and even supports keys that aren't generated by the server.

Michael Brown
  • 9,041
  • 1
  • 28
  • 37