I'm creating a framework MVC to build my applications. In my application I need to use several DBMS s and I need be prepared for that.
I'm thinking in to use Active Record pattern and it have the "connection" (abstract) associated. The Active Record don't know which DBMS to be used. So, I use Factory Method for have abstract which DBMS been used.
How will I build various queries (CRUD) ? Because each DBMS will need specific query.
I'm think that creating various classes "QueryBuilder" it will can to resolve (one class for each DBMS ).
What's think?
To resolve this issue, you can use DAO Layer Pattern. This pattern hides the database specific details from the client. You can define the interface for CRUD operation which your DAO will implement.
In this way, even your DB changes in future, client of DAO layer don't have to worry about the changes.
Refer below wiki page for more details about this pattern.
http://en.wikipedia.org/wiki/Data_access_object
I assume the intent is to insulate the various ActiveRecord objects from the SQL syntax variances between the DBs?
You didn't define what you exacty intended with a design for your query bulder, but I've done once with methods like AddSelection(colName), AddCriteria(colName, ComparisonEnum, value), etc. If that is your approach then if your queries are small/simple enough then a query builder would work. BUT as soon as you need the ability to build complex joins or inner subqueries then you may hit a wall with that approach.
If you need to handle arbitrarily difficult queries then another option is to create a converter or translator. If you were to define a canonical query format, then each DBMS-specific convert would know how to convert from that canonical format to the DB-specific syntax. You've really got to need this functionality to make it worth the effort though.
And finally, your other appraoch is to subclass the ActiveRecord for each DB. So if you have an EmployeeRecord class you can subclass it with OracleEmployeeRecord, MySqlEmployeeRecord, MsSqlServerEmployeeRecord, and the like. Then use an abstract factory to create the appropriate ActiveRecord objects.
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.
I have a typical DAO to fetch SQL objects from a table, but now I need to be able to query for objects placed in another physical database using foreign keys. Due to restrictions in my ORM I cannot create a query that joins over the two databases and hence I need to do this reduction step myself. To not introduce dependencies between DAOs I thought to myself that I should increase the level of abstraction and introduce a service on top of this DAO that does this for me. Is this the way to go or am I more confused than I think I am?
Since your "increased level of abstraction service" will be still "DAO" (and nothing more) I would just call it DAO and inject your base DAO service.
Semantically it will be completely correct.
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.
I frankly haven't got a clue what to search for reagarding my question, so here goes.
I'm trying out some different approaches for a new project I'm starting on.
I have a PostgreSQL DBMS. I have a single DB with multiple schemas. The idea is that there is a "root" schema, which works as a foundation for the other schemas.
What I'm trying to achieve is a sort of "one-way" inheritance. I'd like my queries in the root-tables to not look at the subclassed schemas, but I haven't found a way to do that.
When querying the subclasses, I'd like to join with the base class, but when querying the base class, I don't want to query the subclasses.
I understand the difference between the different inheritance approaches, but I'm just not sure if what I'm trying to do is possible.
My current setup actually works with subclasses in different schemas, but when querying the base class, NHibernate goes to query each of the subclasses to see if the base class is any of those types.
Maybe the behavior is appropriate in some situations, but in others, I'd just like to query the base class "alone".
As another requirement, the base class cannot know about the subclasses (they're like plugins/extensions).
Hope the above made any sense - it was a bit difficult to express.
Thanks in advance...
<class ... polymorphism="explicit">
See http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-class
I figured it out. My problem was in my SubclassMap<>. Apparently NHibernate don't support explicit polymorphism with joined-subclass. I am now joining each subclass using ClassMap<> and calling Join(...) instead. In this scenario, explicit polymorphism works.
Given:
You have an architecture with the layers presentation, business and data.
You are applying domain-driven design.
You are using an object-relational mapper that lets you create object-oriented queries (e.g., NHibernate which lets you create HQL queries).
Question:
Into which layer should you put the object-oriented queries?
My thoughts:
I think putting them into the presentation layer will usually make no sense. But I don't know whether to put them into business or data layer.
Example (NHibernate):
Say your business logic needs some method GetCustomersPossiblyInterestedIn(Product p). You might then create a complex HQL query that selects customer objects where the customer has already bought a product that is in the same category as p.
Argument a)
On the one hand, I'd say this query is clearly business logic, because the decision that a customer is treated as possibly interested in a product based on whether she has bought a product in the same category is a business decision. You might as well select customers who have bought multiple products in the same category with a similar price, e.g.
Argument b)
On the other hand, the business layer should not depend upon the data layer, so directly using NHibernate in the business layer rings an alarm bell.
Possible solution 1)
Create your own object-oriented query language that you use in the business layer and translate to HQL in the data layer.
I think this would cause a lot of overhead. If you use a query language based on query objects instead of a parsed query language, you could probably safe some effort, but my objection still applies.
Possible solution 2)
Directly using NHibernate in the business layer is O.K., because the abstraction level that NHibernate is able to provide with HQL, ISession etc. fits the business layer. There is no need to wrap it.
What do you think?
Edits:
See "Repository is the new Singleton" and "The false myth of encapsulating data access in the DAL" by Ayende Rahien for closely related discussions.
Definitely, avoid putting object-oriented queries into presentation layer. It should ONLY display/use data received from business logic layer (BLL). Without any querying. If you need to query results received from you BLL, then your BLL needs to be extended to provided such data that don't need to be queried.
Your idea to use 'object oriented query language' seams like a good. Usually, this "language' is your DAL :) I would say good example of "object oriented query language" is a properly implemented Data Access Layer (DAL).
From my perspective you DAL should implement 80-90% of all functionality and provide set of functions like that:
Customer GetCustomerById(int customerId);
List GetLastRegisteredCustomers(int count);
etc...
These functions provide the biggest part of required functionality that don't need to be queried.
For all other 10-20% of rarely used queries (you named them "object oriented") your DAL should implement method/methods that return IQueryable result, I would say at least 'GetAll()' method and probably few customizations:
IQueryable GetAll();
IQueryable GetCustomerByCountry(int countryId);
in this case if you will need to find a customer in a country registered this year on you BLL you will call:
List<Customer> customers = GetCustomerRepository()
.GetCustomerByCountry(countryId)
.Where(customer=>customer.RegisterDate.Year==year)
.ToList<Customer>()
;
Guess, you know what provide IQueryable<> interface.
How to work with Linq under NHibernate: Linq to NHibernate.
One additional hint: I would recommend to use 'Repository' pattern for you DAL implementation. Some time ago i used this for general idea: http://habrahabr.ru/blogs/net/52173/ (if you can't read Russian translate whole page with google - it should be readable).
Hope that helps.
I prefer to wrap NHibernate (or other ORM) using some sort of a Repository. For eg. in the case of NHibernate the Repository would wrap the NHibernate session. This repository could be per class (So CustomerRepository and OrderRepository) or if you don't have too many classes in your domain, you could start with a single Repository as well.
This is then the perfect place to put Criteria queries (LoadAllByName, LoadCustomerWithOrder, etc.). If you later need to switch to a different ORM or even a different persistence mechanism (very rare, I would think), you can swap out the whole Data layer including the Repository.
Queries belong in the repository. You may have a function signature for GetCustomersPossiblyInterestedIn(Product p) anywhere it is necessary, but the query itself should only be in a repository class