I've been doing XML transformation for a while in my Java application and I'm still not clear what the options are and what the best option is to read records from a database and insert it in my transformed output file.
What I've been doing so far is querying an Oracle database with xQuery that gave me a nodeset as a result. I then passed this result as a parameter to the transformer and queried that parameter during the transformation to insert data into the appropriate nodes.
Is this the best way of doing it though? My base language again is Java. What would be the other options to get the same result?
Also I think it's worth mentioning that most of the times the db query is based on the content of the source XML file.
Thanks
Have you looked at the Saxon SQL extensions, in particular at <sql:query> extension element?
One possibility is to instantiate a Java object in your XSLT script;
<!-- Connection to the data provider. -->
<xsl:variable name="provider" xmlns:java="http://xml.apache.org/xalan/java"
select="java:my.sample.DataProvider.getInstance()" />
Using it to provide the data later on in the script:
<xsl:template match="node">
<xsl:variable name="mydata" xmlns:java="http://xml.apache.org/xalan/java"
select="java:getdata($provider, string(#attr))" />
This would call the method getData(String) on the object created by the static getInstance() method on your my.sample.DataProvider class.
You can use a setup like this to get values from a cache (for instance the query results you try to pass as parameter in your current setup), or to execute queries while transform is executed (preventing queries to data that is not visited by the transform.)
Related
I have a requirement to get XML data stored in db2. In db2 the XML data is stored in a table column whose type is XML (db2).
Now if i have to retrieve it using plain JDBC (no other choice i have here), what is the java data type in which this should be mapped.
From what i researched, i feel it should be this way.
String xmlData = (String) resultSet.getObject(1);
(assuming 1 is the column index where the xml data is stored)
Is this a viable solution? Any suggestions?
ResultSet has getSQLXML(int) which returns a java.sql.SQLXML object.
SQLXML gives you the most options to access the XML data.
Anyway you have a wide variety of options to retrieve the XML.
According this doc you can simply use ResultSet.getString(int) if you want the data as String.
But as always it depends on the version of your DB2 and your JDBC driver if all these options are supported.
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/
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.
I have a xml file and I want to store it contents in DB.How The format of my xml is not fixed 100%
I have xml file as shown below
<Jb>
<T1>false</T1>
<T2>
<email>dshetyo#adobe.com</email>
<userName>passwd</clusterName>
<passwd>adobe</clusterURL>
<url>dummy</url>
<param1>val </paramY>
<paramN> val </paramN>
</t2>
<fx>
<a >351108</a>
<b >4629 <b>
</fx >
</Jb>
I can have N params eg param1,param2 etc (N not fixed)How can i map it to a relatioanl table structure?
Any other approach?
This is a one to many relationship. You'll want a table like so:
account
id
email
usernmae
parameters
account_id
param_key
param_value
And then your SQL looks roughly like:
select * from account, parameters where account.id = parameters.account_id
Alternatively, you can use a single column to store all of your key value pairs as well. You can do this as a long string, or a clob (depending on what you think is more appropriate performance-wise and what your needs are in terms of size)
(so there would additional parsing necessary, but if you're not looking to select parameters via SQL, this is the way to go)
Usually, XML content is stored in a database in a single TEXT or VARCHAR column.
Because of its free-form structure, it is generally not suitable for O/R mapping.
One option is to insert the XML directly into the table, then use XPath commands to extract the fields on query. XPath is supported by the major databases: MySQL, Oracle, Postgres...
Oracle has XMLDB, their implementation of the XPath functions for searching based on XML. This means that you can define a column as being an XMLType data type, and attach/map schema to this (This aids in validating as well as evolving the XML over time).
XML in MySQL:
http://dev.mysql.com/tech-resources/articles/xml-in-mysql5.1-6.0.html
MySQL appear to support XPath functions as previously mentioned:
http://dev.mysql.com/doc/refman/5.6/en/xml-functions.html
But note, these features are still under development in MySQL.
In java, do we have an open source to generate sql from an xml file? For example, the simplest case is :
<query>
<select>id</select>
<from>student</from>
<equal><column>name</column><val>john</val></equal>
<equal><column>age</column><val>23</val></equal>
<equal><column>registerDate</column><val>03/04/1990</val></equal>
</query>
Then it will generate a sql:
select id
from student
where name = 'john'
and age = 23
and registerDate = '03/04/1990'
Of course, this is simplest case, when we have between, join, it will be more complex. So do we have an open source to handle this? I don't want to use ORM like hibernate, because it goes too far.
Thanks.
Do you have to use this XML format? Was it somehow internally defined?
If your objective on XML is purely making dynamic queries easier to create, you may try MyBatis. It uses XML definition files to group the SQL queries together and allow you to dynamically change queries based on parameters, without the mess of assembling the SQL query with String concatenation. You won't define every element as a XML tag, but only parts of it that may change. Take a look at the MyBatis User Guide for more info and code samples. Here is a quick look at a simple dynamic query:
<select id=”findActiveBlogWithTitleLike” parameterType=”Blog” resultType=”Blog”>
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test=”title != null”>
AND title like #{title}
</if>
</select>
That's just to give you a glimpse of what it would look like. There are plenty of possibilities and tags to help you build whatever query you may need, so I suggest you to take some time to read the user guide to fully understand the framework capabilities.