Where should an JDBC-compliant application store its SQL statements and why?
So far, I managed to identify these options:
- Hardcoded in business objects
- Embedded in SQLJ clauses
- Encapsulate in separate classes e.g.
Data Access Objects - Metadata driven (decouple the object
schema from the data schema –
describe the mappings between them in
metadata) - External files (e.g. Properties or
Resource files) - Stored Procedures
What are the “Pros” and “Cons” for each one?
Should SQL code be considered “code” or “metadata”?
Should stored procedures be used only for performance optimisation or they are a legitimate abstraction of the database structure?
Is performance a key factor the decision? What about vendor lock-in?
What is better – loose coupling or tight coupling and why?
EDITED: Thank you everyone for the answers – here is a summary:
Metadata driven i.e. Object Relational Mappings (ORM)
Pros:
- Very abstract – DB server can be
switched without the need to change
the model - Wide-spread – practically a standard
- Cuts down the amount of SQL needed
- Can store SQL in resource files
- Performance is (usually) acceptable
- Metadata driven approach
- (Database) vendor independence
Cons:
- Hides SQL and true developers
intentions - SQL difficult to be reviewed/changed
by DBA - SQL might still be needed for odd
cases - Can force usage of a proprietary
query language e.g. HQL - Does not lend itself to optimisation
(abstraction) - Can lack referential integrity
- Substitutes for lack of SQL knowledge
or lack of care to code in the DB - Never match native database
performance (even if it comes close) - Model code is very tight coupled with
the database model
Hardcoded/encapsulated in DAO layer
Pros:
- SQL is kept in the objects that
access data (encapsulation) - SQL is easy to write (speed of
development) - SQL is easy to track down when
changes are required - Simple solution (no messy
architecture)
Cons:
- SQL cannot be reviewed/changed by DBA
- SQL is likely to become DB-specific
- SQL can become hard to maintain
Stored Procedures
Pros:
- SQL kept in the database (close to
data) - SQL is parsed, compiled and optimised
by the DBMS - SQL is easy for DBA to review/change
- Reduces network traffic
- Increased security
Cons:
- SQL is tied to the database (vendor
lock-in) - SQL code is harder to maintain
External files (e.g. Properties or Resource files)
Pros
- SQL can be changed without a need to
rebuild the application - Decouples the SQL logic from the
application business logic - Central repository of all SQL
statements – easier to maintain - Easier to understand
Cons:
- SQL code can become un-maintainable
- Harder to check the SQL code for
(syntax) errors
Embedded in SQLJ clauses
Pros:
- Better syntax checking
Cons:
- Ties too closely to Java
- Lower performance than JDBC
- Lack of dynamic queries
- Not so popular
Usually, the more the application grows in terms of size and/or reusability, the more the need is to externalize/abstractize the SQL statements.
Hardcoded (as static final constants) is the first step.
Stored in a file (properties/xml file) is the next step.
Metadata driven (as done by an ORM like Hibernate/JPA) is the last step.
Hardcoded has the disadvantage that your code is likely to become DB-specific and that you need to rewrite/rebuild/redistribute on every change. Advantage is that you have it in 1 place.
Stored in a file has the disadvantage that it can become unmaintainable when the application grows. Advantage is that you don’t need to rewrite/rebuild the app, unless you need to add an extra DAO method.
Metadata driven has the disadvantage that your model code is very tight coupled with the database model. For every change in the database model you’ll need to rewrite/rebuild/redistribute code. Advantage is that it is very abstract and that you can easily switch from DB server without the need to change your model (but ask yourself now: how often would a company switch from DB server? likely at least only once per 3 years, isn’t it?).
I won’t call stored procedures a “good” solution for this. They have an entirely different purpose. Even though, your code would be dependent on the DB / configuration used.