Querying the appropriate database schema - java

This is a follow-on question to my earlier question about specifying multiple schemata in java using jooq to interact with H2.
My test H2 DB currently has 2 schemata, PUBLIC and INFORMATION_SCHEMA. PUBLIC is specified as the default schema by H2. When running a query that should extract information from eg INFORMATION_SCHEMA.TABLES the query fails with a "table unknown" SQL error. I am only able to execute such queries by executing a factory.use(INFORMATION_SCHEMA). There are no build errors etc and eclipse properly autocompletes eg TABLES.TABLE_NAME.
If I dont do this, jooq doesnt seem to prepend the appropriate schema even though I create the correct Factory object for the schema eg
InformationSchemaFactory info = new InformationSchemaFactory(conn);
I read about mapping but am a bit confused as to which schema I would use as the input/output.

By default, the InformationSchemaFactory assumes that the supplied connection is actually connected to the INFORMATION_SCHEMA. That's why schema names are not rendered in SQL. Example:
// This query...
new InformationSchemaFactory(conn).selectFrom(INFORMATION_SCHEMA.TABLES).fetch();
// ... renders this SQL (with the asterisk expanded):
SELECT * FROM "TABLES";
The above behaviour should be documented in your generated InformationSchemaFactory Javadoc. In order to prepend "TABLES" with "INFORMATION_SCHEMA", you have several options.
Use a regular factory instead, which is not tied to any schema:
// This query...
new Factory(H2, conn).selectFrom(INFORMATION_SCHEMA.TABLES).fetch();
// ... renders this SQL:
SELECT * FROM "INFORMATION_SCHEMA"."TABLES";
Use another schema's factory, such as the generated PublicFactory:
// This query...
new PublicFactory(conn).selectFrom(INFORMATION_SCHEMA.TABLES).fetch();
// ... renders this SQL:
SELECT * FROM "INFORMATION_SCHEMA"."TABLES";
Use Settings and an appropriate schema mapping to force the schema name to be rendered.
The first option is probably the easiest one.
This blog post here will give you some insight about how to log executed queries to your preferred logger output: http://blog.jooq.org/2011/10/20/debug-logging-sql-with-jooq/

Related

How to don't write schema name in oracle sql query?

I have Workspace/Schema EDUCATION in Oracle XE.
In my Java code I want execute queries like this: SELECT * FROM Table instead of SELECT * FROM EDUCATION.Table.
When I write query without EDUCATION I have error: table or view does not exist.
I tried to set the default schema to % (screenshot), but it did not help.
How to avoid writing Workspace/Schema name?
If I understand correctly, you want to access tables in other schemas without using the schema name.
One simple way to do this uses synonyms. In the schema you are connect to:
create synonym table for education.table;
Then you can use table where you would use education.table.

Change Table names in derby database using entitymanager

I am using an APACHE DERBY database, and basing my database interactions on EntityManager, and I don't want to use JDBC class to build a query to change my tables' names (i just need to put a prefix to each new user to the application, but have the same structure of tables), such as:
//em stands for EntityManager object
Query tableNamesQuery= em.createNamedQuery("RENAME TABLE SCHEMA.EMP_ACT TO EMPLOYEE_ACT");
em.executeUpdate();
// ... rest of the function's work
// The command works from the database command prompt but i don't know how to use it in a program
//Or as i know you can't change system tables data, but here's the code
Query tableNamesQuery= em.createNamedQuery("UPDATE SYS.SYSTABLES SET TABLENAME='NEW_TABLE_NAME' WHERE TABLETYPE='T'");
em.executeUpdate();
// ... rest of the function's work
My questions are :
This syntax is correct?
Will it work?
Is there any other alternative?
Should I just use the SYS.SYSTABLES and find all the tables that has 'T' as tabletype and alter their name their, will it change the access name ?
I think you're looking for the RENAME TABLE statement: http://db.apache.org/derby/docs/10.10/ref/rrefsqljrenametablestatement.html
Don't just issue update statements against the system catalogs, you will corrupt your database.

Why is Hibernate generating this SQL query?

I'm using Hibernate and a MySql server. I use multiple databases as "namespaces" (e.g. users, transactions, logging etc.).
So, I configued Hibernate to NOT connect to a particular database :
url = jdbc:mysql://127.0.0.1/
The databases where tables are located are defined in the hbm files through the catalog attribute :
<class name="com.myApp.entities.User" table="user" schema="" catalog="users"> ...
When I want to load some data, everything works fine and Hibernate seems to generate the expected SQL queries (by using the catalog prefix in the table names) e.g. :
select id from users.user
However, when I try to add a new record, Hibernate don't use the from [catalog].[table_name] syntax anymore. So I get a MySQL error 'No database selected'.
select max(id) from user
Hibernate is trying the get the future id to create a new record, but it doesn't specify in which database is located the table, it should be :
select max(id) from users.user
Why is Hibernate generating this invalid query ? Have someone ever experienced this problem ?
You need to specify the schema for the generator. See this question on SO for a more detailed answer.

Removing quotes in openjpa generated sql for sybase

I need to be able to refer to a table on a different schema, using OpenJPA to access a Sybase db.
So, for example, I need to select as follows:
SELECT name FROM SHARE.dbo.PROVINCE;
However, the generated SQL is:
SELECT name FROM "SHARE.dbo".PROVINCE;
which Sybase rejects. Without the quotes it works fine.
I'm using the following annotations on the class:
#Entity
#Table(name="PROVINCE", schema="SHARE.dbo")
using schema="SHARE" doesn't work, although it generates the sql without any quotes. (Sybase requires schema.owner.table, so SCHEMA.PROVINCES is an unknown object)
Any thoughts on how to resolve this issue?
Try concatenating the schema to the table name: #Table(name="SHARE.dbo.PROVINCE")
This is a bit of a shot in the dark, but you could try to disable delimited identifier support?
openjpa.DBDictionary=sybase(SupportsDelimitedIdentifiers=false)

Apache Camel example to insert a row in a table

I want to insert exchange.body to a database table for one of the condition of my route.
Is there any example/tutorial of camel-jdbc component to insert message body?
Can I import the SQL statement itself and pass exchange.body to it?
I looked at http://camel.apache.org/jdbc.html example, but could not understand it.
Here Spring example is confusing for me. I didn't get why is it setting the body as SQL query and again importing some query from the class path. (There is no insert query example mentioned here.)
If you want to insert using the same statement (changing the parameters only) - use SQL component.
If you want to insert using arbitrary SQL statement into the component - use JDBC component.
SQL component usage:
from("direct:start").to("sql:insert into table foo (c1, c1) values ('#','#')");
com.google.common.collect.Lists;
producerTemplate.sendBody("direct:start", Lists.newArrayList("value1","value2"));
JDBC component usage:
from("direct:start").to("jdbc:dataSource");
producerTemplate.sendBody("direct:start", "insert into table foo (c1, c1) values ('value1','value2')");
You probably need to do some restructure of your payload before inserting it anyway, so there should probably be no issue to do a transformation using whatever method in Camel to set the body to the appropriate INSERT statement.
The important thing is what kind of payload structure your incoming message have. In the basic case - it's a string - it should be fairly simple
// In a Java bean/processor before the JDBC endpoint.
// Update: make sure to sanitize the payload from SQL injections if it contains user inputs or external data not generated by trusted sources.
exchange.getIn().setBody("INSERT INTO MYTABLE VALUES('" + exchange.getIn().getBody(String.class) + "', 'fixedValue', 1.0, 42)");
In case your message contains complex data structures, this code will of course be more complex, but it's pretty much the same way regular application will generate SQL queries.
The classpath example you are refering to
<jdbc:embedded-database id="testdb" type="DERBY">
<jdbc:script location="classpath:sql/init.sql"/>
</jdbc:embedded-database>
Simply shows how to test the JDBC component by starting a Database server embedded (Apache Derby) and populate it with some initial data (the sql/init.sql file). This part is not really part of the core jdbc component, but simply in the documentation to get up and running a sample without needing to configure a DB server and setup the JDBC connection properties.
That said, you might want to use the SQL component for more complex scenarios.

Categories