There are some limitations of using JDBC and database dependency is one of those limitations.
Is there any pattern or way to achieve database independence in JDBC (without using any other ORM framework or tool).
I have tried to achieve this through dynamic polymorphism (created specific classes for different DBMS and overridden common CRUD operations according to specific SQL syntax).
For example, is there a way to write generic SQL statements so that they can be executed in almost every SQL related DBMS?
I think I'm qualified to answer, being the author of jOOQ, which was already suggested in another answer. As I've shown, it's totally possible to achieve what you're trying to do, but there is a long long road ahead for you, if you want to roll your own.
JDBC is an excellent network protocol abstraction, so it's a great starting point. There are quite a few caveats though as you move on to solving more complex problems inside of an API like the one you're trying to build. For instance:
NULL
values. Sometimes it works, sometimes it doesn't.java.sql.Date
and java.time.LocalDate
? Good luck!TIMESTAMP WITH TIME ZONE
data type there are?INTERVAL
types? Really?OUT
parametersBOOLEAN
typeautoCommit
is set to true?DatabaseMetaData
to reverse engineer your schema? Forget it!ResultSetMetaData
to discover qualified column names? Well...As you've seen, even if JDBC does its job really well for most people (and there's always a hacky workaround for each of the above that works for an individual database. But you want to write an API that works on all databases, so you have to fix / work around all of the above. Trust me. That'll keep you busy for a while!
But thus far, we've only discussed how hard it is to bind to JDBC. We haven't discussed how hard it is to standardise SQL. So let's discuss that for a moment:
LIMIT n OFFSET m
is nice, eh? Or is it LIMIT m, n
? Or TOP n START AT m
? Or OFFSET m ROWS FETCH NEXT n ROWS ONLY
? What if you want to support older databases? Will you roll your own ROW_NUMBER()
filtering? Here, I've documented it for you.SELECT
without FROM
. In other databases, you need something like a DUAL
table. There you go, all documented.DUAL
table, until their parser breaks and you still need it (hello MySQL)SELECT
without FROM
, but they do require FROM
for WHERE
/ HAVING
/ GROUP BY
(SELECT 1 UNION SELECT 2) UNION ALL SELECT 3
. Will it work on all databases? (I mean the parenthesised nesting)EXCEPT ALL
supported? Is EXCEPT
even supported?FULL OUTER JOIN
supported?AS
permitted on derived tables?ORDER BY
clause contain expressions referencing aliases from the SELECT
clause? Or only expressions referencing columns from the FROM
clause?ORDER BY
clause contain expressions at all?ORDER BY
clause?SUBSTRING()
or SUBSTR()
or INSTR()
or what?REPEAT()
function on SQLite
VALUES()
constructor, as in SELECT * FROM (VALUES (1), (2)) t(a)
? Few databases have native supporttable(column)
in one go) if it's not supported? Here's a funky idea.(a, b) > (x, y)
is the same as this: a > x OR a = x AND b > y
. The former isn't supported everywherePostgreSQL's UPDATE .. RETURNING
can be emulated using a PL/SQL block in Oracle 12c:
declare
t0 dbms_sql.number_table;
t1 dbms_sql.date_table;
c0 sys_refcursor;
c1 sys_refcursor;
begin
update "TEST"."T_2155"
set "TEST"."T_2155"."D1" = date '2003-03-03'
returning
"TEST"."T_2155"."ID",
"TEST"."T_2155"."D1"
bulk collect into t0, t1;
? := sql%rowcount; // Don't forget to fetch the row count
open c0 for select * from table(t0);
open c1 for select * from table(t1);
? := c0; // These need to be bound as OracleTypes.CURSOR OUT params
? := c1; // These need to be bound as OracleTypes.CURSOR OUT params
end;
As you can see, it can totally be done. I've done it, it's called jOOQ. It's probably been the biggest challenge of my professional life and it has been fun. jOOQ 3.10 will feature a parser, which can translate from a SQL string (in any dialect) to another SQL string (in a specific dialect), which is the next level of vendor agnosticity.
But it was a long way to go to get here. Before I did jOOQ (started in 2009), I've worked with Oracle SQL and in-house JDBC-based frameworks (like the one you're planning to write) intensively. I wrote jOOQ because I've seen many in-house frameworks being written and none of them did the job well. The developers always tackled SELECT
.. FROM
.. WHERE
- which is the easy part. Some managed to get JOIN
in the game, and perhaps GROUP BY
and that's it. They then abandoned the task, because they had more important stuff to do than maintain boring and buggy infrastructure software.
Now, I don't know what your motivation is to do this yourself, but my advice here is:
You can try building your own jOOQ (or Hibernate). It's a fun challenge. But if you have deadlines, I really suggest you review the above options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With