Question

I don't want to make my code tight coupled to some JDBC driver (for example MySql). I want to make universal code, that can work with many database implementations. And I don't quite understand how to achieve this goal when using JDBC.

I think to achieve this I need only to export driver class name(and connection string) to .properties file (for example "com.mysql.jdbc.Driver"), and then in code use it like this Class.forName(PROPERTIES.getDriverName()).newInstance(); So when I decide to change my database, all what I need to change is jdbc driver name in .properties file (for example to "COM.ibm.db2.jdbc.app.DB2Driver" ), connection string, and change driver's .jar file in classpath.

Is it right?

Was it helpful?

Solution

Loose coupling can be achieved in several ways -

A. Use Hibernate , but this may be an overkill for your needs and hurt performance (if your application performs mostly write operation)

B. Use Spring-JDBC or any other framework that serves as JDBC wrapper - usually they provide some sort of abstraction

C. If your code is Java EE code, you can work with DataSources, and configure them on your Java application server - you will lookup the data source by name, and you will not know the implementation details behind

D. You can make sure you build the application in layers - a business logic layer, that uses a data access layer, which uses some data engine (Make sure your data engine class implement an interface you so u can change implementation easily).

Your Data engine class can read the information about the jdbc driver from a configuration (properties of XML files) - this is basically what Hibernate does , for example.

OTHER TIPS

You got it right. Externalize the driver class name, the database URL, the user and the password, and here you go. That what is done by most "frameworks" anyway: Java EE servers allow configuring datasources in the server, and accessing it using JNDI. Hibernate has entries in its configuration file for this, connection pools usually use an XML or properties file to hold their configuration.

Of course, if you use proprietary SQL code, you won't be able to switch from one database to another so easily, but that's another problem.

This might work for you, sure. I'll be a little more complete for future readers of the question though:

but a lot of the queries you write might be database specific, or rely on certain keywords to be effective. Take for example a common query. You want to list all the products in a database , but show the user 10 at a time:

MySQL:

select * from products LIMIT 0,10

then for the next 10 rows:

select * from products LIMIT 10,10

etc.

Fantastic, so users can use MySQL for the database. Well what if they are using postgres, another free and very popular database? That query isn't going to work:

SELECT * FROM product LIMIT 10 OFFSET 10

So your code isn't portable as much as you think.

One way to get around this is to create your own interfaces (interface Query, interface Access)for all the queries/accesses that you plan on doing, and then have a query factory which can instantiate, based on the DB Dialect (MySQL, postgres, etc) and create MySQLQueryImpl and PostGresQueryImpl (both implementing the Query interface).

You have to code some of the database calls twice, unfortunately, or move them out into a properties file themselves. You can also design the query factor to instantiate from a property file (like you originally want), and allow other users in the future to implement their own Query so the extensibility is there, and you don't have to do it all yourself.

Or...

The other option, which is probably more elegant and error proof (well... maybe) is to let someone else do this for you. Hibernate is a very common tool that abstracts out the database read/writes for you, and can be configured to use a different database just as you want to, only it has years of experience and bug fixes. It's not the easiest thing to learn (for complex queries and joins, etc) but for the basic models and mapping to a database, it will give you everything you want and more, including the ability to turn on/off caching very easily and lazy loading of data so you don't bring in thousands of records that you won't use.It would take you a long time to create and harden a system like this.

Externalizing connection string doesn't enable your application to handle different databases. But here is what you can do.

Use Datasource instead of connection This offers you the ability to create connection many different ways using JNDI, from Connection Pool, etc.

More on Datasource, straight out of javax.sql.DataSource javadoc

A factory for connections to the physical data source that this DataSource object represents. An alternative to the DriverManager facility, a DataSource object is the preferred means of getting a connection.

Define DAO interface for accessing data. Make your application code depend on Interface. You can provide database specific implementation for the DAO interface. When the database changes, create new implementation for the database. Let DAO factory pick and choose the appropriate instance of DAO depending on database.

Libraries like Mybatis, Hibernate which support ORM paradigm automate these steps for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top