I'm currently in the process of creating a data access layer for an application. This application will initially connect to an Oracle database but will later also connect to a DB2 database.
For connecting to the database I will use JDBC. At this time I'm considering my options. As I see it I have two (primary) options.
1) Create a design with support for multiple DAO factories, each instantiating the DAO's specific to their database. Initially, this design will only have one factory. Later it will be extended with a second factory and DAO classes.
2) Create one DAO factory which instantiates multiple DAO's for the different models. This DAO factory builds the DAO's based on a configuration file, which contains the JDBC driver path and connection url.
I'm tempted to choose the second option, which seems to remove quite some code duplication in the DAO's. Could anyone give the pros and cons of both approaches?
Why would you choose for multiple DAO factories (abstract factory pattern) when you don't really need it when using JDBC?
I believe Spring or Guice would be the best and cleanest option for you, where you'd want to pick the appropriate DAO implementation and inject it in the DAO consumer layer. Spring will also enable you to use Spring-JDBC which takes care of most of the boilerplate code making your DAO Impls easy to manage and code. You can also use ORMs with Spring.
Taking into account that you can't use Spring (even though it would save you from a lot of coding), I would say that 2nd variant is more appropriate to you, because you are going to implement dependecy management yourself and 1 dependency (single DAO factory) is always easier than 2.
Though, if you expect that amount of places were DAOs for both databases are used together is not big, then separating them into 2 factories will have a better structural meaning and is more clean. But if you expect, that pretty much every class that uses DAOs will need both worlds (Oracle + DB2), then again stick to the 2nd variant.
In any case, try to consider again about dependecy injection framework usage, because that what you are going to implement yourself anyway with all your factories.
Related
I am trying to use the DAO pattern in my multiple web app projects. I have three different web applications and they share two different databases. Each databases have number of tables.
Now I am wondering how I can make my program modular by using best practice. I am thinking of making:
DAO project which have two factory class for each database, DAO interfaces for each tables and DTO for each tables.
Then in each web app project I am planning to write implementation code for DAO interface and necessary utility class for getting and closing the connections.
Is this approach good? The doubt/problem i am having is with this design if I am going to ship any one of the project I have to ship DAO project also but that will contain unnecessary info about other databases.
Or will it be good to attach all necessary DAO in web app itself? If so then I have to write same DAO ode for each web app.
Hope anyone can provide me the clear path for this DB connection using DAO pattern.
In general, you're headed in the right direction by separating your concerns.
You mention the multiple web apps rely on the two databases. Does each web app rely on both databases? If so, I'd consider creating a single DAO project to encapsulate all the data access logic.
If it's more a mix and match (web app a uses db a, web app b uses db b, web app c uses a and b), I'd consider having two DAO projects, one per database, unless there's a lot of combined logic - that is, when an app uses both databases, it's doing joins between them [yes, I have had projects that do this].
I'd also recommend looking at an Object/Relational Mapping (ORM) framework such as Hibernate and/or a Dependency Injection framework such as Spring, which can help simplify the process of separating the various projects and then using them together.
You're clearly planning a pretty ambitious project, so taking advantage of existing frameworks to minimize recreating the wheel will let you focus on your specific problem domain.
Use JPA to access DB. If not possible then use JdbcTemplate (Spring)
EntityManager (JPA) is a kind of a DAO
DAO only where it makes sense (e.g. complex, reusable logic using an EntityManager)
Use pooled connections/ DataSources
DTO are usually only needed if your objects need to leave the JVM (e.g. remote EJB services, web services,...)
use EJBs for container-managed transactions
consider the Gateway pattern (a stateful session bean and an extended persistence context, see "Real World Java EE Patterns – Rethinking Best Practices" by Adam Bien) and just return the attached entity.
I want to implement a sample in java that reads a configuration from some config file and, based on that, when user interacts with the page the application will store some data on either MySql or Oracle according to the configuration parameters. How can we implement this sample in most efficient and smart way?
Indeed using Hibernate or JPA allows you to abstract the database differences away.
With a dependency injection framework like Spring or Guice you can then create 2 service instances which differ only in the persistence manager which is injected.
In this case you can keep almost 100% of the code identical for the 2 databases which guarantees they will not get out of sync over time.
Make an interface for data storage, and use that in your application
Make an abstract class which implements this interface and implements the functionality which MySQL and Oracle have in common.
Make two classes, one for MySQL and one for Oracle which implement the database-specific stuff.
In your configuration, specifiy which class to use (MySQL or Oracle database class).
Maybe use something like Hibernate, which abstracts the database away from you.
Following up on #Sjoerd's answer:
Any tools or open source libs that can be helpful?
Hibernate or some other JPA implementation is your best bet.
Alternatively, Spring has some JDBC support classes that do some of the work ... if you can figure out which of the various alternatives is a good match to your requirements.
Unfortunately, implementing an application that works against multiple database backends is hard work, no matter how you do it. In my experience, you usually end up with a solution that doesn't perform as well as a solution that is tailored to one and only one database back end.
If I had my way, database vendors who refuse to implement the SQL standard would be first against the wall ... come the revolution.
Stepwise, what would be a good way of integrating Spring and Hibernate into an existing JSF application that doesn't use ORM?
1) You would need to design the domain model first and then map it to the database. You could use hibernate reverse engineering tools for this.
2) Other option is to manually map your current objects(DTO) to database tables. Since you use JSF, I assume you'd be having some objects currently.
3) Design the Service Layer around the objects.
Spring -
1) You could use Spring to provide hibernate template, provide common services through bean.
2) You can manage the transaction in Spring.
I would recommend first to write tests to check your code of your previous persistent mechanism. This code could be used to check the correct behavior of our ORM integration.
As mentioned by other answers, having a clear DAO defined by interface helps to bound the DAO code.
Map the domain objects first, then write your DAO, then your service objects (which take care of large atomic suite of operations by enclosing its in a transaction).
Use persistence mechanism which is vendor-agnostic (JPA is the good and only choice).
Start with one kind of database and stick with it during all the migration. In very uncommon cases, you can meet subtle differences between databases which could be very hard to solve, especially if you're a beginner.
When starting, use automatic generation of database (generateDdl for hibernate subsystem) and then, when things starts to be stabilized, force #Table and #Column annotations to fix name of each column. At this point, write a SQL script which generate the database with empty tables. The reason if to fix your architecture and be sure you're controlling the database organization.
If you're serious about ORM, please look at Java Persistence With Hibernate of Christian Bauer (Manning publications), this is "the bible" about hibernate and JPA on Java.
If you've written Spring properly, you should have DAO/repository interfaces. If that's the case, all you have to do is write a new implementation of that interface using Hibernate, test it, and change your Spring configuration to inject it.
ORM presumes that you have an object model in place to map to a relational schema. If you don't, I would advise against using ORM. Better to use iBatis or JDBC in that case.
I started experimenting with Spring Roo just recently. It does a very nice job helping one build a domain model with integrated persistence rather quickly. As it adds persistence functionality in aspects, I started think about the following question:
Roo adds finders (load an instance of a class from the database which meets variable criteria) in an aspect to the actual class/entity. In DDD this is IMHO the responsibility of repositories. Repositories are explicit classes which show up in the design. Of course as an aspect the repository functionality is hidden in an entity and is pretty much invisible.
So here is the question: Is an aspect a real substitute for a explicit repository class? Are there any downsides to the Roo AOP approach?
Adding finders to your domain classes feels more natural from a user's point of view but it mingles your layers. Grails uses the same approach by adding static finder*() save(), ... methods.
Apart from the aestetics it might have practical drawbacks when not used in web application setting:
Your domain classes are now tied to your database. If you transfer these objects to rich clients via RMI or HttpInvoker the client cannot and often may not use the find* methods because there is no session / database connection available on the client.
I generally prefer allowing domain classes to reference service layer interfaces to prevent an anemic domain model (http://martinfowler.com/bliki/AnemicDomainModel.html). This has its own set of drawbacks but at least provides a clear boundary. On the client the concrete implementation behind a service interface can then just proxy all method calls to the server (or just use a synamic proxy with spring remoting or sth similar).
So to answer your question: It might be a substitute but you should be aware of the possible negative consequences which make your domain classes (i.e. your core business logic) less portable between systems.
This depends on how complicated your applications persistence layer is and how much control you have over it. If your application is simple enough to be implemented via JPA, then it all could be handled via Roo aspects. However if you are mapping legacy tables or need advanced DB stuff, then you may find yourself in a situation where Spring-JDBC is the only way out and in these cases a repository/dao model may still be useful.
I consider it logical inconsistent (and a break of layer responsibility) to be mixing two persistence models and so as most of my applications requires such advanced DB constructs I stick strictly with a repository model.
I think adding repository methods to domain objects is bad design. The right place would be static methods in the domain class. But domain objects and their management are two different things that should be separated. I would prefer domain objects and repositories.
I guess the motivation was to achieve something Rails/Grails like with Java.
Our application has a service layer and a DAO layer, written as Spring beans.
While testing the Service Layer- I do not want to depend upon a real database so I am mocking that by creating a 'Mock' Impl for the DAO layer
So when I am testing the Service layer- I chain the Service layer beans to the Mock DAO beans
And in Production- will chain the Service layer to the 'real' DAO beans
Is that a good idea ?
Any alternate suggestion on how to mock the database layer ?
Clarification:This question is about testing the Service Layer and not the DAO layer.
While testing the service layer- I assume that either the DAO layer has already been tested or doesn't need testing.
The main thing is- how do we test service layer- without being dependent upon the DAO implementation- hence I am mocking the DAO layer
This is a technique we've been using for many years now. Note that when it comes to mocking the DAO interfaces you have some choices:
Create mock instances as real Java classes
Use a dynamic mocking framework such as jMock (my preference) or EasyMock
Dynamic mocking frameworks allow you to stub out a variety of circumstances (no data, 1 row, many rows, exception throwing) without having to create complex classes to stub out the behavior you wish to test
That's a great way to use mocking to test the database. I don't think any alternative suggestion is necessary; I think you've got the right technique already!
You are definitely on the right track.
My mocking framework of choice is Mockito
As I understand the question it is explicitly dedicated to best practices regarding testing DAO layers, as mocking a database seems nnot so straightforward as mocking the DAO layer when testing services.
Personally I'd raise the question back if it's reasonable to really unit test a DAO layer in the classical unit testing meaning. If you design your DAO layer properly it does not do much more than mapping domain objects to queries.
That said I alway propose to use an embedded database like H2, HSQL or the Java 6 embedded Derby to do things like this as mocking a datasource is really much more effort than simply raising an embedded database. Spring 3 will provide a nice builder pattern to create such databases on the fly. RC1 of it will also introduce a jdbc namespace to ease setup further. See this one for details.
But even with current Spring 2.5 branch using an embedded database is just a matter of taking the databases JAR and setting up a DataSource accordingly.