We're using the DTO pattern to marshal our domain objects from the service layer into our repository, and then down to the database via NHibernate.
I've run into an issue whereby I pull a DTO out of the repository (e.g. CustomerDTO) and then convert it into the domain object (Customer) in my service layer. I then try and save a new object back (e.g. SalesOrder) which contains the same Customer object. This is in turn converted to a SalesOrderDTO (and CustomerDTO) for pushing into the repository.
NHibernate does not like this- it complains that the CustomerDTO is a duplicate record. I'm assuming that this is because it pulled out the first CustomerDTO in the same session and because the returning has been converted back and forth it cannot recognise this as the same object.
Am I stuck here or is there a way around this?
Thanks
James
You can re-attach an object to a session in NHibernate by using Lock - e.g.
_session.Lock(myDetachedObject, NHibernate.LockMode.None);
which may or may not help depending on exactly what is happening here. On a side note, using DTO's with NHibernate is not the most common practice, the fact that NHibernate (mostly) supports persistence ignorance means that typically DTO's aren't as widely used as with some other ORM frameworks.
It's really about how NHibernate session works. So if you within a session pull an instance of your CustomerDTO and then after a while you should get the same CustomerDTO (say by primary key) - you actually will get reference to the very same object like you did in your first retrieval.
So what you do is that you either merge the objects by calling session.Merge or you ask your session for the object by calling session.Get(primaryKey) do your updates and flush the session.
However as suggested by Steve - this is not usually what you do - you really want to get your domain object from the datastore and use DTOs (if neede) for transferring the data to UI, webservice whatever...
As others have noted, implementing Equals and GetHashCode is a step in the right direction. Also look into NHibernate's support for the "attach" OR/M idiom.
You also have the nosetter.camelcase option at your disposal: http://davybrion.com/blog/2009/03/entities-required-properties-and-properties-that-shouldnt-be-modified/
Furthermore, I'd like to encourage you not to be dissuaded by the lack of information out there online. It doesn't mean you're crazy, or doing things wrong. It just means you're working in an edge case. Unfortunately the biggest consumers of libraries like NHibernate are smallish in-house and/or web apps, where there exists the freedom to lean all your persistence needs against a single database. In reality, there are many exceptions to this rule.
For example, I'm currently working on a commercial desktop app where one of my domain objects has its data spread between a SQL CE database and image files on disk. Unfortunately NHibernate can only help me with the SQL CE persistence. I'm forced to use a sort of "Double Mapping" (see Martin Fowler's "Patterns of Enterprise Application Architecture") map my domain model through a repository layer that knows what data goes to NHibernate and what to disk.
It happens. It's a real need. Sometimes an apparent lack in a tool indicates you're taking a bad approach. But sometimes the truth is that you just truly are in an edge case, and need to build out some of these patterns for yourself to get it done.
I'm assuming that this is because it
pulled out the first CustomerDTO in
the same session and because the
returning has been converted back and
forth it cannot recognise this as the
same object.
You are right. Hibernate can't. Consider implementing Equals and Hashcode to fix this. I think a re-attach may only work if you haven't loaded the object within this session.
Related
I'm currently tring to port an application using hibernate to ABAP.
So short version is: I've (at least) two tables, let's say Entity(entity_id, ...) and SubEntity(sub_entity_id, entity_id).
Now in ABAP OO I'm representing these entities as classes, like zcl_app_entity. Now I'm wondering how I could use ABAP to persist these entities and relationships.
I've use-cases like:
Lock entity, and then add subentity
Get all subEntities and send them via http as json
In Java with JPA I'd do something like
Entity entity = userRepository.findById(entityId);
entity.lock(); // granted, this mechanism would on DB Level here while ABAP needs ABAP Locks
entity.getSubEntities.add(address);
There's a session with UnitOfWork automatically with the repository call. But as far as I'm aware ABAP doesn't offer a Repository pattern which automatically transforms classes to managed entities.
I could of course add INSERT etc directly into the add calls, or create a load / persist method on every class. But then I lose the testability.
I could create Repositories myself, passing in the objects. But then my Objects are repository aware itself (addAddress would call the repository).
Another way would be in the service class to call the repository, and then pass that object to the add method after it's persisted. Quite error prone.
Also lazy loading of e.g. xstrings (like 50MB) would be great, this won't work when the object has no access to the repository / sql interface to load on demand though.
I'd be super suprised if there isn't something like this (JPA/Hibernate), since these are common patterns.
IEntityRepository, ISubEntitiyRepository, IMyService (calls repo interfaces)
All calls make objects managed, maybe with OneToMany etc relationships, rollbacks, lazy load.
Weirdly I found the most ABAP way to have some logic in classes (e.g. the Entity->lock( ), entity->add_subentity( xyz ) but then just use an SQL persistency interface to get all data and return some structures. There wouldn't really be OO relationships. At most a class would be used as a short time driver of a struct. But when I'd say update all sub_entities it would be more like data_provider->get_sub_entity( entity_id ) which returns an internal table. And then the requestor has to persist it again if required data_provider->update_sub_entity_status( entity_id, 'R' )
So how do I use Object–Relational mapping in ABAP, e.g. when I want to update the status of all sub_entities of entitiy X to 'DONE' while keeping it testable?
You can take a look at the basic ABAP persistence service.
In se24 if you create a class, you can mark it as "persistent".
Eg SFLIGHT.
https://blogs.sap.com/2012/04/18/abap-persistent-object-services-demystified/#:~:text=The%20Persistence%20Object%20Services%20can,again%20when%20you%20need%20them.
There is an generated example on every system CL_SPFLI_PERSISTENT
If you have used ORMs in other languages like c# , this will be a very disappointing experience.
This toolset began around 20 yrs ago, but offers a questionable return on invest if you ask me.
Apart from the fact the approach doesnt conform to traditional OO principals.
When this first came out SAP already had 3GL code updating traditional
tables. Most developers even SAP internal, had no clear idea how to implement an ABAP OO model.
90% of the code SAP delivered didnt use this type of model. So there where no good examples to base your own work on.
Unfortunately it never took off and was never extended to have the functionality expected in a true ORM persistence tool.
I dont recall seeing anything inside the toolset that manages things like cascade delete. Nor A proper class relationship model?
Please correct me if I missed that.
If you ask me, sap generated a class with GET and SET methods and a PERSIST method and that was where it stopped.
Actually using Classes not DDIC structures as the model and implementing things like cascade delete look outstanding.
If you google SAP and ORM you will see a Javascript tool using Hibernate and HANA as the DB. Not an ABAP based tool.
or you will see ORM meaning Operational Risk Mgt.
That pretty much says it all. The ABAP layer has a toy Class generator but no true ORM tool like entity framework on .net.
Our current application uses a smart object style for working with the database. We are looking at the feasibility of moving to PetaPoco instead. Looking over the features I notice you can add attributes to make it easier to CRUD objects. Does adding these attributes have any negative side effects that I should be aware of?
Has anyone found a reason NOT to use these decorators?
Directly to the use of the POCO object instance itself? None.
At least not that I would be aware of. Jon Skeet should be able to provide more info because he knows compiler inner workings through and through, so he knows exactly what happens with this metadata after it's been compiled.
Other implications indirectly related to these
There are of course implications when accessing these declarative attributes, because they're read using reflection which is normally a slow process.
But there's nothing to worry here, because PetaPoco is a smart library and reads these only once then compiles & caches these things, so you only get penalized once then you get blazing performance afterwards. Because it uses compiled code.
Non-performance related implications
By putting attributes (any) on your classes/properties/methods you somehow bind your code to particular engine that will use this class, because they're directives for this particular engine to understand your code.
In case of PetaPoco attributes this means that your class can be used with PetaPoco but not with some other DAL (ie. EF) unless you add attributes of that one as well (EF Code First uses the very same approach with attributes).
The second implication is related to back-end database. In case you rename a table, column or any other part that is provided in your PetaPoco attribute as a constant magic string, you will subsequently have to change this string as well. This just means that you have to be thorough when doing database changes...
One downside is that it breaks the separation between the "domain" layer and the "data" layer, since it introduces the PetaPoco file (which contains data logic) to domain classes that should really not have any knowledge or dependency on the data layer.
If you're doing a single-project MVC app or something then it's okay to just use the Models directory for both, but for non-trivial and separated apps you'll have to have two PetaPoco files or play around with abstracting portions of the file in order to annotate your models without making them "know too much" about the underlying data, or else have you specify the table and/or primary key name all over the place.
Say I have a User object, which is generated by a Usermapper. The User object does not know anything about the database/repository in use (which I believe to be good design).
When creating a User, I only want it to have it filled by the mapper with the most trivial things e.g. Name, address etc. However after object instantiation I might have a method userX.getTotalDebt(), getTotalDebt() would need to reconnect to the database , because I don't want this relatively expensive operation to be done for every User instantiation (multiple tables needed etc). If I'd simply insert some sql in the getTotalDebt() or a dependency back to the Mapper where the coupledness is growing tight very fast.
There is an obvious good/best practice for this, because it's a situation arises often, however I can't find it or I'm looking at this problem totally from a wrong angle.
Say I have a User object, which is generated by a Usermapper. The User object does not know anything about the database/repository in use (which I believe to be good design).
They are often referred to as POCOs (Plain Old CLR Objects).
When creating a User I only want it to have it filled by the mapper with the most trivial things e.g. Name, address etc.
There are several OR/M layers which can achieve this. Use either nhibernate or Entity Framework 4.1 Code First.
I might have a method userX.getTotalDebt(), getTotalDebt() would need to reconnect to the database
Then it's not a poco anymore. Although it is possible using a transparent proxy. Both EF and nhibernate supports this and it's called Lazy Loading.
There is an obvious good/best practice for this, because it's a situation arises often, however I can't find it or I'm looking at this problem totally from a wrong angle
I usually keep my objects dumb and disconnected. I use the Repository pattern (even if I use nhibernate or another orm) since it makes my classes testable.
I either use the repository classes directly or create a service class which contains all logic. It depends on how complex my application is.
We are taking a long, hard look at our (Java) web application patterns. In the past, we've suffered from an overly anaemic object model and overly procedural separation between controllers, services and DAOs, with simple value objects (basically just bags of data) travelling between them. We've used declarative (XML) managed ORM (Hibernate) for persistence. All entity management has taken place in DAOs.
In trying to move to a richer domain model, we find ourselves struggling with how best to design the persistence layer. I've spent a lot of time reading and thinking about Domain Driven Design patterns. However, I'd like some advice.
First, the things I'm more confident about:
We'll have "thin" controllers at the front that deal only with HTTP and HTML - processing forms, validation, UI logic.
We'll have a layer of stateless business logic services that implements common algorithms or logic, unaware of the UI, but very much aware of (and delegating to) the domain model.
We'll have a richer domain model which contains state, relationships, and logic inherent to the objects in that domain model.
The question comes around persistence. Previously, our services would be injected (via Spring) with DAOs, and would use DAO methods like find() and save() to perform persistence. However, a richer domain model would seem to imply that objects should know how to save and delete themselves, and perhaps that higher level services should know how to locate (query for) domain objects.
Here, a few questions and uncertainties arise:
Do we want to inject DAOs into domain objects, so that they can do "this.someDao.save(this)" in a save() method? This is a little awkward since domain objects are not singletons, so we'll need factories or post-construction setting of DAOs. When loading entities from a database, this gets messy. I know Spring AOP can be used for this, but I couldn't get it to work (using Play! framework, another line of experimentation) and it seems quite messy and magical.
Do we instead keep DAOs (repositories?) completely separate, on par with stateless business logic services? This can make some sense, but it means that if "save" or "delete" are inherent operations of a domain object, the domain object can't express those.
Do we just dispense with DAOs entirely and use JPA to let entities manage themselves.
Herein lies the next subtlety: It's quite convenient to map entities using JPA. The Play! framework gives us a nice entity base class, too, with operations like save() and delete(). However, this means that our domain model entities are quite closely tied to the database structure, and we are passing objects around with a large amount of persistence logic, perhaps all the way up to the view layer. If nothing else, this will make the domain model less re-usable in other contexts.
If we want to avoid this, then we'd need some kind of mapping DAO - either using simple JDBC (or at least Spring's JdbcTemplate), or using a parallel hierarchy of database entities and "business" entities, with DAOs forever copying information from one hierarchy to another.
What is the appropriate design choice here?
Martin
Your questions and doubts ring an interesting alarm here, I think you went a bit too far in your interpretation of a "rich domain model". Richness doesn't go as far as implying that persistence logic must be handled by the domain objects, in other words, no, they shouldn't know how to save and delete themselves (at least not explicitely, though Hibernate actually adds some persistence logic transparently). This is often referred to as persistence ignorance.
I suggest that you keep the existing DAO injection system (a nice thing to have for unit testing) and leave the persistence layer as is while trying to move some business logic to your entities where it's fit. A good starting point to do that is to identify Aggregates and establish your Aggregate Roots. They'll often contain more business logic than the other entities.
However, this is not to say domain objects should contain all logic (especially not logic needed by many other objects across the application, which often belongs in Services).
I am not a Java expert, but I use NHibernate in my .NET code so my experience should be directly translatable to the Java world.
When using ORM (like Hibernate you mentioned) to build Domain-Driven Design application, one of good (I won't say best) practices is to create so-called application services between the UI and the Domain. They are similar to stateless business objects you mentioned, but should contain almost no logic. They should look like this:
public void SayHello(int id, String helloString)
{
SomeDomainObject target = domainObjectRepository.findById(id); //This uses Hibernate to load the object.
target.sayHello(helloString); //There is a single domain object method invocation per application service method.
domainObjectRepository.Save(target); //This one is optional. Hibernate should already know that this object needs saving because it tracks changes.
}
Any changes to objects contained by DomainObject (also adding objects to collections) will be handled by Hibernate.
You will also need some kind of AOP to intercept application service method invocations and create Hibernate's session before the method executes and save changes after method finishes with no exceptions.
There is a really good sample how to do DDD in Java here. It is based on the sample problem from Eric Evans' 'Blue Book'. The application logic class sample code is here.
I think I am at a impasse here. I have an application I built from scratch using FluentNHibernate (ORM) / SQLite (file db). I have decided to implement the Unit of Work and Repository Design pattern. I am at a point where I need to think about the end game, which will start as a WPF windows app (using MVVM) and eventually implement web services / ASP.Net as UI.
Now I already created domain objects (entities) for ORM. And now I don't know how should I use it outside of ORM. Questions about it include:
Should I use ORM entity objects directly as models in MVVM? If yes, do I put business logic (such as certain values must be positive and be greater than another Property) in those entity objects? It is certainly the simpler approach, and one I am leaning right now. However, will there be gotchas that would trash this plan?
If the answer above is no, do I then create a new set of classes to implement business logic and use those as Models in MVVM? How would I deal with the transition between model objects and entity objects? I guess a type converter implementation would work well here.
To answer the first part of your question, yes your business logic and validation should go in your entities. The point of NHibernate is to let you design your entities to be persistence ignorant. That means that you should, whenever possible, be designing your entities as you would if you didn't care about persistence. This isn't entirely feasible as you'll soon find out (you'll need to make your properties virtual in order to support lazy loading and if you want to use NHibernate Validator you'll be decorating your properties with validation attributes), but for the most part NHibernate does a good job of staying out of your way.
As for whether to use your entities as the models, you'll get mixed reviews on that. Ideally, you would create separate viewmodel classes and map from your entities to the viewmodel so that your views will only access to the bare minimum of information they need. This also goes a long way in preventing N+1 access issues. However, doing so is often a huge pain. Granted, there are tools like AutoMapper that will make it easier from transposing your entity properties to a viewmodel.