DAL design: handling access to 2 or more tables in a database? - data-access-layer

I'm developing on php at the moment, but this question should be language independent.
For DB access, I have always heard people promoting the "one class per table" practice, so I'm wondering where to put access methods that accesses 2 or more tables at the same time (using JOIN, for example). I can think of 3 ways to deal with this:
Create a separate class for the combination of the 2 tables
Put the access methods in the class for both tables
Have the BLL call each db class separately and write custom logic to get what you need (i.e. do the join outside of SQL)
What is the best practice and why?
Thanks!

Of your three options 1 like one the best. As long as there isn't too much business logic in it. "Too" much is subjective, mind you.
Another option is to create a database view that combines the 2 tables. You then create a class for that as if it was a table.

Related

Ruby on Rails Best Design Pattern Instead of Single Table Inheritance?

I'm a junior developer working on a new Rails App and need some assistance in deciding which design pattern is best to use to model different types of orders. I was planning on utilizing the Single Table Inheritance pattern for these problems, but have heard several developers say I should stay away from this pattern. Any ideas are appreciated!
Orders need different types. Each type shares some database columns, however will also need some columns which are not shared by the other types (as we further develop the business and begin to handle new types of orders). I want to avoid duplicating columns in different database tables, and I also want to avoid having one table for everything as each type will not need everything from a single table.
Orders can be created by either customers or retailers on behalf of one of their customers. Another type of Order is the WelcomeKit which we send to customers directly before they send in their order
All Orders need the following:
customer_id
fullfilled - boolean
fullfilled_date
outgoing_shipment_id
total
sub_total
discount_total
All RepairOrders also need the following:
arrived (boolean)
arrival_date
incoming_shipment_id
repairer_id (the store doing the repair)
All RetailOrders need everything from Orders and RepairOrders and also:
retailer_id (the store creating the order)
retailer_order_id (the id of the order from the retailer)
All WelcomeKits only need information from the Order table.
Is Single Table Inheritance the best way to handle this? Are there any other patterns that are better suited for long term maintainability? Any specific help on both database and model design would be awesome! Thanks.
I highly recommend you to read the book by Sandi Metz, Practical Object-Oriented Design in Ruby, as it touches upon this very subject in great detail. Since I don't have it with me right now, I will copy a short paragraph written by Ben Johnson that kind of summarizes the overall strategy:
Always prefer composition to inheritance (classes) unless you can
defend inheritance. Also, consider if you have one basic thing with
subtypes or something that is made up of parts.
If X is-a Y → Inheritance (class)
If X has-a Y → Composition
IF X behaves-like-a Y → Duck type (module)
Good design naturally progresses towards small, independent objects that rely on abstractions.
I think that in your particular situation inheritance may be a good fit.

Hibernate vs SQL

I'm currently implementing a new functionality to a tool in an e-learning platform. I need to retrieve some columns from 3 different tables in the database. The particular tool is implemented with Hibernate technology where a class is mapped to a database table.
However, I need to use some information from different tables to build a single class.
Can you Hibernate provide this sort of implementation?
If not, will it be appropriate for me to use SQL in this situation?
Is it a good practice to have 2 database technologies in one place?
Hibernate is made to do this, multiple tables either through relationships such as many-to-one, or multiple tables which represent different subtypes, etc. You can use entity-name to map a single class to two different tables for different situations. So the answer is yes.
As to doing Hibernate and hand-coding SQL in the same application, I think it's a very common practice, sometimes it's 200% easier to do than figure out the Hibernate mapping for a small detail. I'm referring to something like JDBC, but as nowaq points out, you cna do this in Hibernate as well.
Yes, Hibernate can do this. Take a look at this post: Mapping One Java Class to Two Database Tables with Hibernate.
Maybe its not your case, but in general having two tables mapped to a single class may be a signal that you've got something wrong with your design. Make sure to take a second look.
Try not to mix too many frameworks and technologies in your app. You may end up with bunch of dependencies and very complex, unclean code.

SQL Views vs. Database Abstraction (in code)

I just learned about SQL views, which seem nice, but if I abstract table joining to a data access class, wouldn't this accomplish the same thing? What are your thoughts on this? I've never used views before so this is all pretty new to me.
Remember that not all applications that hit your your database may be using the same data access classes. Nor are they used in exports or reporting. The views are a better place to abstract some complex things (such as how to get certain kinds of financial information) if you want consistentcy. However, don't go overboard with abstracting things to views either. Views should not call views (at least in Sql Server but I suspect in other dbs as well) because you have to materialize all the underlying views to get the data in the top layer. This means to get to the three records you want, you might end up materializing millions of records first. With large tables this can create a performance problem of nightmare proportions. Further views that call views that call views become a truly difficult maintenance problem when something needs to be fixed.
The main purpose of a view is to abstract the complexity of creating a specific result set. In large relational databases, you often need to join many tables together to get useful data. By creating views, any client can access it without needing access to your database access layer.
Additionally, almost all RDMSs will optimize a view by caching the parsed execution plan. If you query is complicated enough, you may hit a substantial query planning hit when executing the query. However, with a view, the query plan is created and saved when the view is created or when it is used for the first time.
Views can also be great for maintaining backward compatibility. Say you have a table that needs to change, but it would be difficult to update all the clients at once to use the new table schema. You could create a view with the old table name that provides the backwards compatibility. You can then create a new table with the new schema.
I'd say one of the main purposes of views are to simplify the interface betwen a complex database (whether it be star schema/OLTP) and another layer (user / OLAP cube / reporting interface).
I guess broadly I'd say that if there can be multiple ways that you can access your database (MS Excel/.net app) then you would want to use SQL views as then they are available to all, otherwise if you create a data access class in c# (e.g.), then it wont be usable by the MS Excel people.
Views simply put, reduce the complex look of all the joins put together in a sql query.
So instead of executing a join on 30 tables, a view does the 30 table join but then can be reused in another view / sproc to simply say:
SELECT * FROM myView
Rather then:
SELECT...
FROM
...
INNER JOIN
...
INNER JOIN
...
INNER JOIN
...
It basically hides all these details. This article should be a great reference: http://www.craigsmullins.com/cnr_0299b.htm
The point is views are not physical structures, they are simply a relational model or "view" of one or many tables in a database system.
Abstracting joins to a data access class might give you the same data, but it might not give you the same performance.
Also, for most businesses the database is a shared resource. It's sensible to assume that there are applications already hitting the database that cannot or will not go through your data access class. It's also sensible to assume that some future applications cannot or will not go through your data access class. As a trivial example, the command-line interface and the graphical interface to any dbms you use won't be using your data access class.
Views are also the way SQL databases implement logical data independence. Think of them as part of the public interface.
Views can be shared by interactive SQL users, report writers, OLAP tools, and applications written in different languages or by multiple programming teams that don't share classes with eahc other.
As such, it's a good way for database designers to share standardized queries across the whole community of users of the data.

What are views good for?

I'm just trying to get a general idea of what views are used for in RDBMSes. That is to say, I know what a view is and how to make one. I also know what I've used them for in the past.
But I want to make sure I have a thorough understanding of what a view is useful for and what a view shouldn't be useful for. More specifically:
What is a view useful for?
Are there any situations in which it is tempting to use a view when you shouldn't use one?
Why would you use a view in lieu of something like a table-valued function or vice versa?
Are there any circumstances that a view might be useful that aren't apparent at first glance?
(And for the record, some of these questions are intentionally naive. This is partly a concept check.)
In a way, a view is like an interface. You can change the underlying table structure all you want, but the view gives a way for the code to not have to change.
Views are a nice way of providing something simple to report writers. If your business users want to access the data from something like Crystal Reports, you can give them some views in their account that simplify the data -- maybe even denormalize it for them.
1) What is a view useful for?
IOPO In One Place Only•Whether you consider the data itself or the queries that reference the joined tables, utilizing a view avoids unnecessary redundancy. •Views also provide an abstracting layer preventing direct access to the tables (and the resulting handcuffing referencing physical dependencies). In fact, I think it's good practice1 to offer only abstracted access to your underlying data (using views & table-valued functions), including views such as CREATE VIEW AS SELECT * FROM tblData1I hafta admit there's a good deal of "Do as I say; not as I do" in that advice ;)
2) Are there any situations in which it is tempting to use a view when you shouldn't use one?
Performance in view joins used to be a concern (e.g. SQL 2000). I'm no expert, but I haven't worried about it in a while. (Nor can I think of where I'm presently using view joins.)Another situation where a view might be overkill is when the view is only referenced from one calling location and a derived table could be used instead. Just like an anonymous type is preferable to a class in .NET if the anonymous type is only used/referenced once. • See the derived table description in http://msdn.microsoft.com/en-us/library/ms177634.aspx
3) Why would you use a view in lieu of something like a table-valued function or vice versa?
(Aside from performance reasons) A table-valued function is functionally equivalent to a parameterized view. In fact, a common simple table-valued function use case is simply to add a WHERE clause filter to an already existing view in a single object.
4) Are there any circumstances that a view might be useful that aren't apparent at first glance?
I can't think of any non-apparent uses of the top of my head. (I suppose if I could, that would make them apparent ;)
Views can be used to provide security (ie: users can have access to views that only access certain columns in a table), views can provide additional security for updates, inserts, etc. Views also provide a way to alias column names (as do sp's) but views are more of an isolation from the actual table.
In a sense views denormalize. Denormalization is sometimes necessary to provide data in a more meaningful manner. This is what a lot of applications do anyway by way of domain modeling in their objects. They help present the data in a way that more closely matches a business' perspective.
In addition to what the others have stated, views can also be useful for removing more complecated SQL queries from the application.
As an example, instead of in an application doing:
sql = "select a, b from table1 union
select a, b from table2";
You could abstract that to a view:
create view union_table1_table2_v as
select a,b from table1
union
select a,b from table2
and in the app code, simply have:
sql = "select a, b from union_table1_table2_v";
Also if the data structures ever change, you won't have to change the app code, recompile, and redeploy. you would just change the view in the db.
Views hide the database complexity. They are great for a lot of reasons and are useful in a lot of situations, but if you have users that are allowed to write their own queries and reports, you can use them as a safeguard to make sure they don't submit badly designed queries with nasty cartesian joins that take down your database server.
The OP asked if there were situations where it might be tempting to use a view, but it's not appropriate.
What you don't want to use a view for is a substitute for complex joins. That is, don't let your procedural programming habit of breaking a problem down into smaller pieces lead you toward using several views joined together instead of one larger join. Doing so will kill the database engine's efficiency since it's essentially doing several separate queries rather than one larger one.
For example, let's say you have to join tables A, B, C, and D together. You may be tempted to make a view out of tables A & B and a view out of C & D, then join the two views together. It's much better to just join A, B, C, and D in one query.
Views can centralize or consolidate data. Where I'm at we have a number of different databases on a couple different linked servers. Each database holds data for a different application. A couple of those databases hold information that are relavent to a number of different applications. What we'll do in those circumstances is create a view in that application's database that just pulls data from the database where the data is really stored, so that the queries we write don't look like they're going across different databases.
The responses so far are correct -- views are good for providing security, denormalization (although there is much pain down that road if done wrong), data model abstraction, etc.
In addition, views are commonly used to implement business logic (a lapsed user is a user who has not logged in in the last 40 days, that sort of thing).
Views save a lot of repeated complex JOIN statements in your SQL scripts. You can just encapsulate some complex JOIN in some view and call it in your SELECT statement whenever needed. This would sometimes be handy, straight forward and easier than writing out the join statements in every query.
A view is simply a stored, named SELECT statement. Think of views like library functions.
I wanted to highlight the use of views for reporting. Often, there is a conflict between normalizing the database tables to speed up performance, especially for editing and inserting data (OLTP uses), and denormalizing to reduce the number of table joins for queries for reporting and analysis (OLAP uses). Of necessity, OLTP usually wins, because data entry must have optimal performance. Creating views, then, for optimal reporting performance, can help to satisfy both classes of users (data entry and report viewers).
I remember a very long SELECT which involved several UNIONs. Each UNION included a join to a price table which was created on the fly by a SELECT that was itself fairly long and hard to understand. I think it would have been a good idea to have a view that to create the price table. It would have shortened the overall SELECT by about half.
I don't know if the DB would evaluate the view once, or once each time in was invoked. Anyone know? If the former, using a view would improved performance.
Anytime you need [my_interface] != [user_interface].
Example:
TABLE A:
id
info
VIEW for TABLE A:
Customer Information
this is a way you might hide the id from the customer and rename the info to a more verbose name both at once.
The view will use underlying index for primary key id, so you won't see a performance loss, just better abstraction of the select query.

What to do with queries which don´t have a representation in a domain model?

This is not specific to any language, it´s just about best practices. I am using JPA/Hibernate (but it could be any other ORM solution) and I would like to know how do you guys deal with this situation:
Let´s suppose that you have a query returning something that is not represented by any of your domain classes.
Do you create a specific class to represent that specific query?
Do you return the query in some other kind of object (array, map...)
Some other solutions?
I would like to know about your experiences and best practices.
P.S.
Actually I am creating specific objetcs for specific queries.
We have a situation that sounds similar to yours.
We use separate objects for reporting data that spans several domain objects. Our convention is that these will be backed by a view in the database, so we have come to call them view objects. We generally use them for summarising complex data into a flat format.
I typically write a function that performs a query using SQL and then puts the results into either a list or dictionary (in Java, I'd use either an ArrayList or a HashMap).
If I found myself doing this a lot, I'd probably create a new file to hold all of these queries. Otherwise I'd just make them functions in whatever file they were needed/used.
Since we're talking Java specifically, I would certainly not create a new class in a separate file. However, for queries needed in only one class, you could create a private static inner class with only the function(s) needed to generate the query(s) needed by that class.
The idea of wrapping that up the functionality in some sort of manager is always nice. It allows for better testing, and management therefore of schema changes.
Also allows for easier reuse in the application. NEVER just put the sql in directly!!!. For Hibernate I have found HQL great for just this. In particular , if you can use Named queries. Also be careful of adding an filter values etc use "string append", use parameters (can we say SQL injection ?). Even if the SQL is dynamic in terms of the join or where criteria, have a function in some sort of manager is always best.
#DrPizza
I will be more specific. We have three tables in a database
USER
PROJECT
TASK
USER to TASK 1:n
PROJECT to TASK 1:n
I have a query that returns a list of all projects but showing also some grouped information (all tasks, open tasks, closed tasks). When returned, the query looks like this
PROJECTID: 1
NAME: New Web Site
ALLTASK: 10
OPENTASK: 7
CLOSEDTASK: 3
I don´t have any domain class that could represent this information and I don´t want to create specific methods in Project class (like getAllTasks, getOpenTasks) because each of these methods would trigger a new query.
So the question is:
I create a new class (somenthing like ProjectTasksQuery) just to hold that information?
I return information within array or map?
Something else?
You might feel better after reading about Data Transfer Objects. Some people plain don't like them, but if it feels like a good fit to you, it probably is.