I am looking for an alternative to hibernate.globally_quoted_identifiers for jdbc in order to generate SQL with quotes (to escape reserved keywords) around table names.
We are migrating an oracle database to an h2 in-memory database, and one of the tables is named LIMIT, which is obviously a keyword and bad practice but unfortunately we do no have control over the database structure and it is not something that can be changed.
I found this page that suggests that is can be done on a transactional level, but we need it to be applied globally.
Related
I'm trying to access data in multiple databases on a single running instance. the table structures of these databases are all the same; As far as I know, create a new connnection using jdbc is very expensive. But the connection string of jdbc require format like this
jdbc:mysql://hostname/ databaseName, which needs to specify a specific database.
So I'm wondering is there any way to query data in multiple databases using one connection?
The MySQL documentation is badly written on this topic.
The SELECT Syntax page refers to the JOIN Syntax page for how a table name can be written, even if you don't use JOIN clauses. The JOIN Syntax page simply says tbl_name, without further defining what that is. There is even a comment at the bottom calling this out:
This page needs to make it explicit that a table reference can be of the form schema_name.tbl_name, and that joins between databases are therefore posible.
The Schema Object Names page says nothing about qualifying names, but does have a sub-page called Identifier Qualifiers, which says that a table column can be referred to using the syntax db_name.tbl_name.col_name. The page says nothing about the ability to refer to tables using db_name.tbl_name.
But, if you can refer to a column using db_name.tbl_name.col_name, it would only make sense if you can also refer to a table using db_name.tbl_name, which means that you can access all your databases using a single Connection, if you're ok with having to qualify the table names in the SQL statements.
As mentioned by #MarkRotteveel in a comment, you can also switch database using the Connection.setCatalog(String catalog) method.
This is documented in the MySQL Connector/J 5.1 Developer Guide:
Initial Database for Connection
If the database is not specified, the connection is made with no default database. In this case, either call the setCatalog() method on the Connection instance, or fully specify table names using the database name (that is, SELECT dbname.tablename.colname FROM dbname.tablename...) in your SQL. Opening a connection without specifying the database to use is generally only useful when building tools that work with multiple databases, such as GUI database managers.
Note: Always use the Connection.setCatalog() method to specify the desired database in JDBC applications, rather than the USE database statement.
I am a newbie and have some question on using jdbc with java:
What changes in the code I will have to make to:
change database type? (i.e. from PostgreSQL to MySQL)
use the table in the code after I decide to drop one of the colums from that table.
Also - how to make queries cached?
change database type? (i.e. from PostgreSQL na MySQL)
Replace the MySQL JDBC driver in the classpath with the PostgreSQL JDBC driver. Update the JDBC connection URL to point to PostgreSQL DB instead of MySQL DB. If necessary, also update your SQL queries to replace any MySQL-specific SQL functions/clauses by PostgreSQL-specific ones.
use the table in the code after I decide to drop one of the colums from that table.
Remove the column in question from the SQL queries. If necessary, also update the entity (the custom Javabean class which you have to represent one row of the DB) to remove the property and getter/setter.
Also - how to make queries cached?
Use PreparedStatement instead of Statement. If possible, replace all the JDBC code by a fullworthy ORM such as JPA or good ol' Hibernate. They not only minimizes JDBC boilerplate code to oneliners, but they also offers second-level caching capabilities as well.
I need to use an Entity framework with my application, and I have used table - partitions in Oracle database. With simple JDBC, I am able to select data from a specific partition. But I don't know whether I can do the same with hibernate or Eclipse link (JPA). If someone knows how to do that, please do let me know.
usually the select statement in JDBC - SQL is,
select * from TABLE_NAME partiton(PARTITON_NAME) where FIELD_NAME='PARAMETER_VALUE';
How can I do the same with Hibernates or JPA?
Please share at least a link for learning sources.
Thanks!!!
JPA or any other ORM framework does not support Oracle partition tables natively (atleast in my knowledge).
There are different possible solutions though, depending on the nature of your problem:
Refactor your classes so that data that needs to be treated differently in real-life, belongs in a separate class. Sometimes this is called vertical partitioning (partitions are not obtained across rows, rather across columns).
Use Oracle partition tables underneath and use native SQL queries or stored procedures from JPA. This is just a possibile solution (I haven't attempted this).
Use Hibernate Shards. Although the typical use case for Hibernate Shards is not for a single database, it presents a singular view of distributed databases to an application developer.
Related:
JPA Performance, Don't Ignore the Database
EclipseLink supports partitioning or sharding with different options.
You can find more about this and examples here:
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Data_Partitioning
Table partitioning is data organization on physical level. In a word, partitioning is a poor man index. Like the later, it is supposed to be entirely transparent to the user. A SQL query is allowed to refer to the entire table, but not partition. Then, it is query optimizer job to decide if it can leverage a certain partition, or index.
We use Oracle on a project and would like to also support MySQL. How close are their SQL dialects?
Is it perhaps even possible to use the same SQL source for both without too many gymnastics?
Details:
We're using iBatis, a persistence manager that cleanly segregates the SQL statements into resource files. But we work at the SQL level, which has its advantages (and disadvantages).
We'd prefer not to move to an object-relational mapper like Hibernate, which would fully shield us from dialect differences.
We've tried hard to keep to a generic subset of Oracle SQL.
There's no PL/SQL.
We don't use stored procedures or triggers (yet, anyway).
We use check constraints, unique constraints, and foreign key constraints.
We use ON DELETE CASCADEs.
We use transactions (done at the iBatis API level).
We call a few Oracle timestamp functions in the queries.
We would use the InnoDB storage engine with MySQL (it supports transactions and constraints).
So what are your thoughts? Would we need to maintain two different sets of iBatis SQL resource files, one for each dialect, or is it possible to have a single set of SQL supporting both MySQL and Oracle?
Final Update: Thanks for all the answers, and especially the pointers to Troels Arvin's page on differences. It's really regrettable that the standard isn't more, well, standard. For us the issues turn out to be the MySQL auto-increment vs. the Oracle sequence, the MySQL LIMIT vs. the Oracle Rowumber(), and perhaps the odd function or two. Most everything else ought to transfer pretty easily, modulo a few edits to make sure we're using SQL-92 as #mjv points out. The larger issue is that some queries may need to be hand-optimized differently in each DBMS.
Expect a few minor bumps on the road, but on whole should be relatively easy.
From the list of features you currently use, there should only be a few synctactic or semantic differences, in general easy to fix or account for. The fact that you do not use PL/SQL and/or Stored Procedures is a plus. A good rule of thumb is to try and stick to SQL-92 which most DBMSes support, in particular both Oracle and MySQL. (Note this is not the current SQL standard which is SQL-2008).
A few of the differences:
"LIMIT" is a famous one: to limit the number of rows to retrieve in the results list, MySQL uses LIMIT n, at the end of the query, Oracle uses RowNumber() in the WHERE clause (which is pain, for you also need to reference it in the SELECT list...)
Some datatypes are different. I think mostly BOOLEAN (but who uses this ;-) ) Also some I think subtle differences with the DATETIME type/format.
Some function names are different (SUBSTRING vs. SUBSTR and such...)
Just found what seems to be a good resource about differences between SQL implementations.
Reading the responses from others, yeah, DDL, could be a problem. I discounted that probably because many applications do not require DDL, you just need to set the data schema etc. at once, and then just use SQL for querying, adding or updating the data.
I believe that maintaining a single set of SQL resource files with MySQL and Oracle, has several disadvantages as being caught between backward compatibility and solve a particular problem. it is best to have a sql for each SQL engine and thus maximize the capabilities of each.
Features that look identical in a brochure may be implemented very differently.
see these examples
Limiting result sets
MYSQL
SELECT columns
FROM tablename
ORDER BY key ASC
LIMIT n
ORACLE
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
columns
FROM tablename
)
WHERE rownumber <= n
Limit—with offset
MYSQL
SELECT columns
FROM tablename
ORDER BY key ASC
LIMIT n OFFSET skip
ORACLE
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY key ASC) AS rn,
columns
FROM tablename
)
WHERE rn > skip AND rn <= (n+skip)
You can check this Comparison of different SQL implementations
In addition to the stuff others have mentioned, oracle and mysql handle outer joins quite differently. Actually, Oracle offers a syntax that mySql won't cope with, but Oracle will cope with the standard syntax.
Oracle only:
SELECT a.foo, b.bar
FROM a, b
WHERE a.foo = b.foo(+)
mySql and Oracle:
SELECT a.foo, b.bar
FROM a
LEFT JOIN b
ON (a.foo=b.foo)
So you may have to convert some outer joins.
You definitely won't be able to keep your DDL the same. As far as DML goes, there are many similarities (there's a core subset of ANSI SQL standard supported by every database) but there are some differences as well.
To start, MySQL uses auto increment values and Oracle uses sequences. It's possible to work around this (sequence + trigger on Oracle side to simulate auto increment), but it's there. Built-in functions are quite different.
Basically, depending on what exactly you intend to use it may or may not be possible to keep one set of statements for both. Incidentally, even with Hibernate dialects it's not always possible to have the same set of queries - HQL is great but not always enough.
Oracle treats empty strings as nulls. MySQL treats empty strings as empty strings and null strings as null strings.
How can I handle an array in a prepared statement? i.e, I want to do a query and one of the parameters I get is an array of strings which I want to use in the query (Don't select rows that have a field that's in the array)?
Some JDBC drivers may already (before JDBC 4) contain proprietary extensions that support array-type parameters in prepared statements - you would need to consult with API for this. This would mean that you have to use and manipulate array-like type in SQL.
One work around would be using temporary tables. These are meta-steps for such solution:
Begin transaction (this is automatic if you are inside transactional
method - EJB or Spring);
Using JDBC batch insert with prepared statement create and populate a temporary table with arrary elements (temporary table must have transactional scope - this is also proprietary to databases but supported by Oracle at least);
Construct your desired SQL that includes a join to temporary table to use array values (it could be explicit inner or outer JOIN or implicit join, e.g. using EXISTS, etc.);
Commit (or rollback if application exception) transaction (this should destroy temporary table; concurrent transactions should have no conflict for the same name of temporary table).
Example: IN expression gets replaced with JOIN to temporary table.
This probably won't help you now, but I read that JDBC 4 will support array types as defined in the 2003 version of SQL.
That pretty much depends upon RDBMS being used. Often such functionality can be accomplished using vendor's jdbc driver extensions.
2 variants I found are (for Oracle):
http://blogs.itemis.de/kloss/2009/03/05/arrays-preparedstatements-jdbc-and-oracle/
http://www.angelfire.com/home/jasonvogel/java_jdbc_arrays.html
Try to look if that would help you.