JDBC:is it possible to execute multi-database Querys in java? - java

I want to execute an sql-query over 2 databases using java
but have some problems finding out how to do it without writing everything by myself
maybe someone has an idea how to do it.
example:
database1
table1(names): id,Name,zip,something
database2
table2(towns): id,townname,zip
SELECT *
FROM database1.names, database2.towns
WHERE database1.names.zip = database2.towns.zip
the example works in mysql when i use phpMyAdmin and the User has rights on both databases
edit:
The question is: How do i get Java to execute such a query since i can only connect to one database(?)
or: How can I connect to 2 Databases executing an Sql Query that uses tables from both databases using java.
the way i execute sql commands in java looks like:
Connection c = DriverManager.getConnection("jdbc:mysql://localhost/database?user=root&password=");
PreparedStatement pstmt = c.prepareStatement("Select * from something");
pstmt.executeQuery();
but i cant use that to get a Sql Query that uses tables from 2 databases?

Assuming that these databases are not visible from the same datasource, you have to use a mediation software to query on them, such as http://www.unityjdbc.com/doc/multiple/multiplequery.php.
It's not a trivial problem, since your "SQL" will have to deal with each datasource availability and transaction.
Some DB vendors provide some sort of dblinks (e.g. http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5005.htm) that help you a little to deal with heterogeneous DBs.
So it would be nice if you narrow your question to what DBMSs you are interested.

Related

Same SQL Query returning 2 different results

I have a java application that does a SQL query against an Oracle database, that for some reason gives way less values when executed from the SQL Developer and from the application itself.
Now to the technicalities. The application produces a connection to the db using a wrapper library that employs c3p0. The c3p0 config has been checked, so we know that this things can't be:
-Pointing to wrong database/schema
-Restricted user
Then there's the query:
select to_char(AGEPINDW.TRANSACTION.TS_TRANSACTION,'yyyy-mm') as Time,result, count(*) as TOTAL, sum(face_value) as TOTAL_AMOUNT
from AGEPINDW.TRANSACTION
where (ts_transaction >= to_timestamp(to_char(add_months(sysdate,-1),'yyyy-mm'),'yyyy-mm')
and ts_transaction < to_timestamp(to_char(sysdate,'yyyy-mm'),'yyyy-mm')) and service_id in (2,23)
group by to_char(AGEPINDW.TRANSACTION.TS_TRANSACTION,'yyyy-mm'), result;
It doesn't have any parameter and is executed via your standard PreparedStatement. Yet the return from the app is wrong and I don't know what may be. Any suggestions?

How to externalize an insert file SQL query

In my application, I want to externalize SQL query (in .properties files for example). But sometimes I had to insert the entire content of a text file into a CLOB column.
This is the code I use now:
String requete = "the content of the file in xml";
PreparedStatement prepareStatement = con.prepareStatement("INSERT INTO \"TABLE\".\"_XML\" (ID, BLOC_XML) VALUES ('1',?)");
prepareStatement.setCharacterStream(1, new StringReader(requete), requete.length());
I really need to decouple the SQL logic from the application business logic. Any suggestions to tackle this problem.
Thanks.
It's not a good idea to externalize the SQL queries. Imagine that someone would change the .properties file to something like
drop table really_important_stuff;
Furthermore, as a developer I would prefer to have the SQL queries as close to the source code as possible. So that I do not need to look them up in some other resource.
It's simple to gain control of the complexity using DAO pattern for example.

Connecting to Oracle with JDBC causes queries to return zero rows.

So I have been playing around with querying databases using the standard
Statement s = connection.createStatement();
ResultSet rs = s.executQuery(queryString);
ResultSetMetadata rsmd = rs.getMetaData();
while(rs.next)){
String code = "";
String value = "";
for(int i = 1; i <= rsmd.getColumnCount(); i++){
Object obj = rs.getObject(i);
if(i == 1){
code = obj.toString():
}
else{
label = obj.toString();
}
}
//Store code and labels in map
}
...go on to close statement and move on.
I am trying to select two columns from a table in each instance.
For the most part this works well. When working with MySql & Microsoft Sql databases I get a result set full of data in the table. However when I try to do this with an Oracle database I get an empty result set.
I have tested my query string in the SQL Developer application and it works fine, returns my data. But the result set doesnt contain anything. The resultSet metadata says that it has two columns though. Is there anything I need to do when interacting with an Oracle Database that is different from the other two? Thanks.
If your query works when you run it against the Oracle database, and you know the code works since you've run it against MySQL, then some other things to try are:
1.) Make sure your JDBC connection URL is correct. Are you sure you are connecting to the database that you intend to? (i.e. - the one that would return the rows you expect?)
2.) Take into account credentials. Make sure you are using the same credentials through JDBC that you are when connecting to Oracle directly.
3.) Make sure both connections are being made from the same machine and with the same environment. Oracle drivers rely on environment variables to find a file (I believe it is called tnsnames.ora, or something like that) that contains the alias & connection info. Getting different versions of that file could point you to different Oracle instances.
4.) Try manually specifying your schema name in the query. So instead of select * from my_table use select * from my_schema.my_table. Sometimes Oracle clients will configure their sessions to have default schemas set up in their preferences.
5.) If your are attempting to select data that you've inserted with your Oracle client, make sure you've committed the transaction in your Oracle client so that the data is visible to other sessions.
One last debugging tool to use is to try connecting via the Squirrel DB client. Squirrel is a 100% pure java SQL client that connects to any DB using JDBC. It would be a good test to make sure your JDBC Driver, Connection URL, etc. are all valid.
The database table has records but the JDBC client can't retrieve the records. Means the JDBC client doesn't have the select privileges. Please run the below query on command line:
grant all on emp to hr;

JDBC joins across two MySQL databases on the same server?

Basically I need to run the following query through jdbc. Both databases are MySQL and on the same server.
SELECT * FROM DB1.ACCOUNT a
JOIN DB2.ITEM i ON a.AccountID = i.AccountID
My jdbc connection is set up like this:
Class.forName("com.mysql.jdbc.Driver").newInstance();
DB1 = DriverManager.getConnection("jdbc:mysql://serverloc.com:3300/DB1", "username", "password");
DB2 = DriverManager.getConnection("jdbc:mysql://serverloc.com:3300/DB2", "username", "password");
This is where I run into problems. I can now create a statement against DB1 or DB2, but I can't find a way to JOIN against both databases. I've tried running my query against one of the databases (below) but that returns null.
Statement statement = DB1.createStatement();
ResultSet resultSet = statement.executeQuery(" QUERY HERE ");
I've seen that you can use UnityJDBC to run JOIN queries across DB's, but I'm looking for a free/open source option.
Thanks!
1) Yes, you can "join" between two different databases in mySQL.
2) No, you don't need two different connections to do it.
For example:
http://www.webhostingtalk.com/showthread.php?t=476982
p2.upc_code FROM db1.products p1 LEFT OUTER JOIN db2.products p2 ON p1.prod_id=p2.prod_id";

What are alternatives to JDBC driver for access PostgreSQL database

I'm using official JDBC driver for PostgreSQL, but I'm stuck with the following issues:
No support for PostgreSQL-ish data structures such as UUIDs.
Common JDBC weirdness, such as:
No function to escape values for consuming by PostgreSQL.
Limited support for executing heterogeneous statements in batch.
No rewriting of multiple insert statements into single insert statement when inserting many rows in one table.
So, the question — is there any PostgreSQL database driver which can leverage full power of PostgreSQL without much boilerplate? I'm also use Scala language for development, so if driver is designed specifically for Scala it would be so much awesome awesome.
Some of this seems to be (unless I'm not understanding) user error in using JDBC. JDBC is a pretty ugly API, so never ask if you can do it elegantly, just ask if you can do it at all.
Escaping and inserting multiple rows should be handled, as #ColinD and #a_horse pointed out, with Prepared statements and batch operations. Under the hood, I would expect a good JDBC implementation to do the things you want (I am not familiar with PostgreSQL's implementation).
Regarding UUIDs, here is a solution:
All that PostgreSQL can do is convert string literals to uuid.
You can make use of this by using the data type
org.postgresql.util.PGobject, which is a general class used to
represent data types unknown to JDBC.
You can define a helper class:
public class UUID extends org.postgresql.util.PGobject {
public static final long serialVersionUID = 668353936136517917L;
public UUID(String s) throws java.sql.SQLException {
super();
this.setType("uuid");
this.setValue(s);
}
}
Then the following piece of code will succeed:
java.sql.PreparedStatement stmt =
conn.prepareStatement("UPDATE t SET uid = ? WHERE id = 1");
stmt.setObject(1, new UUID("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"));
stmt.executeUpdate();
The driver supports batched statements to speed up bulk inserts.
And using batched statements is a lot more portable than using proprietary INSERT syntax (and as far as I can tell, there is no big different between a multi-row insert and batched inserts)
Check out PreparedStatement.addBatch()
The reason why UUID is not supported is probably that UUID is not part of the Postgres core, just a contrib module.
Edit
Regarding the execute heterogeneous statements
The Postgres driver does support different types of statements in the a batch.
The following works fine:
Connection con = DriverManager.getConnection("jdbc:postgresql://localhost/postgres", "foo", "bar");
con.setAutoCommit(false);
Statement stmt = con.createStatement();
stmt.addBatch("create table foo (id integer, data varchar(100))");
stmt.addBatch("insert into foo values (1, 'one')");
stmt.addBatch("insert into foo values (2, 'two')");
stmt.addBatch("update foo set data = 'one_other' where id = 1");
stmt.executeBatch();
con.commit();
Although you do lose the automatic escaping that PreparedStatement gives you.
I realise this doesn't answer your entire question, but hopefully it will be useful all the same.
I'm using Java 6 and Postgres 8.4. The driver I'm using is in my Maven POM file as:
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-702.jdbc4</version>
</dependency>
I'm using PreparedStatement.getObject() and PreparedStatement.setObject() with Java's java.util.UUID class to retrieve and store UUIDs.
For example:
pstm.setObject(1, guid); //where pstm is a PreparedStatement and guid is a UUID
and:
//where rs is a ResultSet
UUID myGuid = (UUID) rs.getObject("my_uuid_column_name");
Works fine.
With newer drivers, the following is alsow supported
UUID myGuid = rs.getObject("my_uuid_column_name", UUID.class);
No support for PostgreSQL-ish data structures such as UUIDs.
On the contrary, the current JDBC driver (9.2-1002 JDBC 4) for Postgres 9.x does indeed support UUID via the setObject and getObject commands. You cannot get any more direct or simpler than that (in any database, Postgres or any other) because JDBC does not recognize UUID as a data type.
As far as I can tell, there is no need to create a helper class as suggest in another answer by Yishai.
No need to do any casting or go through strings.
See my blog post for more discussion and code example.
Code example excerpt:
java.util.UUID uuid = java.util.UUID.randomUUID();
…
preparedStatement.setObject( nthPlaceholder++, uuid ); // Pass UUID to database.
Take a look at O/R Broker, which is a Scala JDBC-based library for relational database access.

Categories

Resources