Best way to create a query that uses tables from multiple schemas? - java

I'm working on a webapp served by Tomcat and Apache httpd the uses Struts 1.3.6 and Tomcat 6.
This app talks to Oracle and MySQL databases. The Oracle DB has 14 different schemas and I have a select query that I want to put into an hbm.xml file that uses 8 tables from 3 of the Oracle schemas. The intent is to dynamically add addition where clauses based on user input from the DynaActionForm.
I'm not allowed to build the select as an ad-hoc query and put it in the factory or action as shown in Hibernate - Complex Query from multiple Tables to one object.
Is this possible? If so, examples of this being done would be helpful.
Thanks
EDIT: I should have noted that the is a Hibernate session manager for the MySQL DB plus another for each of the Oracle schemas.
EDIT: The query in quesion...
select distinct
ca.addr_no as customer_number, decode(max(ctn.telephone_no),min(ctn.telephone_no),max(ctn.telephone_no),max(ctn.telephone_no)||', '||min(ctn.telephone_no)) as phone, ca.secondary_addressable_object||' '||ca.primary_addressable_object||' '||ca.street_name as street,
ca.primary_addressable_object, ca.street_name, ca.town_name as suburb, ca.postcode, ii.incident_ref, rd.report_ref, ii.description, ii.inc_category_id, ii.oz_name,
isl.look_up_description as status, ii.group_id, rlu.look_up_description as cause, to_char(ii.creation_date,'dd/mm/yyyy hh24:mi') as creation_date, nvl(cpa.link_reference,'VACANT') as nmi,
rc.report_id, ii.creation_date, ii.primary_ref, (ii.completed_date - ii.creation_date) as duration
from
tcs.inc_incident ii, pbr.rpt_details rd, enmac.look_up_list isl,
pbr.rpt_incident ri, pbr.rpt_reason rr, pbr.rpt_look_up rlu,
pbr.rpt_restoration_customers rc, tcs.cd_telephone_no ctn, tcs.cd_addresses ca,
tcs.cd_cust_property_assoc cpa, pbr.rpt_restoration_stages rs
where
ii.incident_id(+) = ri.incident_id||''
and ri.report_id||'' = rd.report_id(+)
and ii.status+0 = isl.look_up_reference(+)
and isl.look_up_name(+)||'' = 'Incident Status'
and ri.report_id||'' = rr.report_id(+)
and rr.cause_group||'' = rlu.look_up_code(+)
and rlu.look_up_field(+)||'' = 'CAUSE_GROUP'
and ri.report_id(+) = rc.report_id||''
and rc.pro_number(+) = ca.addr_no+0
and rc.stage_id||'' = rs.stage_id(+)
and rc.report_id||'' = rs.report_id(+)
and cpa.customer_no+0 = ctn.pro_number(+)
and cpa.customer_no(+) = ca.addr_no+0
and rs.status(+) = 0
optionally:
and ri.storm_flag(+) != 1 and rd.status(+) != -6
Continuing:
and ca.addr_no in (
With a while bunch more sub selects which vary depending on user input in the form.
I know that I'll need to convert from the old Oracle join style to the ANSI standard as part of this...

Related

Spring JPA Specification - Generate a Plain SQL Where-Clause

we have Spring Hibernate code which generates a Spring JPA data Specification object. This works well (we can use the Specification object to do things like get count). Is there a way to get a plain SQL where-clause from the specification object somehow?
The current code is:
// The line below builds the spec based on business logic. Won't go in the details here, but it is working.
Specification<Crash> querySpec = buildQuerySpec(query);
long count = myDataRepository.count(querySpec);
// Here is what I need: a simple plain T-SQL / Microsoft SQL Server where-clause to be used on other disconnected systems. So something like this:
String whereClause = query.Spec.getPlainSQLWhereClause(...); // e.g. weather in ("raining", "cold") and year in (2014, 2015)
Reason: the specification object (and its related repository) are used in the main system. Now we have other completely disconnected/separate enterprise systems (Esri GIS system), where its APIs can only use plain SQL where-clause.
P.S. I know there's not much code to work with, so some pointers/guides will be much appreciated.

Flyway partial migration of legacy application

In an application with a custom database migrator which we want to replace with Flyway.
These migrations are split into some categories like "account" for user management and "catalog" for the product catalog.
Files are named $category.migration.$version.sql. Here, $category is one of the above categories and $version is an integer version starting from 0.
e.g. account.migration.23.sql
Although one could argue that each category should be a separate database, in fact it isn't and a major refactoring would be required to change that.
Also I could use one schema per category, but again this would require rewriting all SQL queries.
So I did the following:
Move $category.migration.$version.sql to /sql/$category/V$version__$category.sql (e.g. account.migration.1.sql becomes /sql/account/V1_account.sql)
Use a metadata table per category
set the baseline version to zero
In code that would be
String[] _categories = new String[] { "catalog", "account" };
for (String _category : _categories) {
Flyway _flyway = new Flyway();
_flyway.setDataSource(databaseUrl.getUrl(), databaseUrl.getUser(), databaseUrl.getPassword());
_flyway.setBaselineVersion(MigrationVersion.fromVersion("0"));
_flyway.setLocations("classpath:/sql/" + applicationName);
_flyway.setTarget(MigrationVersion.fromVersion(_version + ""));
_flyway.setTable(category + "_schema_version");
_flyway.setBaselineOnMigrate(true); // (1)
_flyway.migrate();
}
So there would be the metadata tables catalog_schema_version and account_schema_version.
Now the issue is as follows:
Starting with an empty database I would like to apply all pre-existing migrations per category, as done above.
If I remove _flyway.setBaselineOnMigrate(true); (1), then the catalog migration (the first one) succeeds, but it would complain for account that the schema public is not empty.
Likewise setting _flyway.setBaselineOnMigrate(true); causes the following behavior:
The migration of "catalog" succeeds but V0_account.sql is ignored and Flyway starts with V1_account.sql, maybe because it somehow still thinks the database was already baselined?
Does anyone have a a suggestion for resolving the problem?
Your easiest solution is to keep the schema_version tables in another schema each. I've answered a very similar question here.
Regarding your observation on baseline, those are expected traits. The migration of account starts at v1 because with the combination of baseline=0, baselineOnMigrate=true and a non empty target schema (because catalog has populated it) Flyway has determined this is a pre-existing database that is equal to the baseline - thus start at v1.

MySQL Query Parsing using java

I need to parse a query which a user enters, say in a text box, and then what I need, is that I want to encrypt all the values in query leaving the query keywords. To convert it into an equivalent query that can be performed on an encrypted database.
Such as,
select name from employee where salary = 10000
I need an equivalent query as,
select name_enc from employee_enc where salary_enc = 10000_enc
where name_enc,employee_enc, salary_enc and 10000_enc are the encrypted values of name, employee, salary and 10000. I need to do this in java and the the database I'm using is MySQL Server where the table Employee is already encrypted.
Please provide any necessary help. Thanks in advance.
You may want to consider using code from Alibaba's Druid project. Although designed as a sophisticated connection pooling library, this project supports a very advanced parser and AST for ANSI SQL and non-ANSI dialects such as MySQL, Oracle, SQL Server, etc. The project is open source and bears the very liberal Apache License Version 2.0.
The main entry points into this part of the library is SQLUtils.java. You can use values returned from SQLUtils.parseStatements to access a typed model of the statements:
List<SQLStatement> statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
for (SQLStatement statement : statements) {
if (statement instanceof SQLSelectStatement) {
SQLSelectStatement createTable = (SQLSelectStatement) statement;
// Use methods like: createTable.getSelect().getQuery().
}
}
If you don't need to do it manually use SQL's included encryption and encoding operations.
If you need to do it manually split your SQL query string by spaces and ignore SQL key words as you loop to encrypt. Remember to encode your cipher results with base 64 or hex to ensure data integrity.
private String encryptSQLQuery(String plainSQLQuery){
StringBuilder cipherQuery = new StringBuilder();
String plainQuery = plainSQLQuery;
String[] splitQuery = plainQuery.split("\\s+");
for(String queryWord : splitQuery){
if(!isSQLKeyWord(queryWord))
queryWord = cryptoObject.encryptAndEncode(queryWord);
cipherQuery.append(queryWord);
cipherQuery.append(" ");
}
return cipherQuery.toString();
}
Note that you will have to implement the isSQLKeyWord() and CryptoObject.encryptAndEncode() methods.

Consult 2 class in Hibernate Search DSL

I'm using hibernate search DSL 4.4.0. And I met a problem recently.
E.g, I have 2 classes INDEXING and DATA_PROPERTY and I can't change them or creat a new class to associate 2 of them.
Now in the SQL, I use
SELECT IND.RDF_RESOURCE
FROM INDEXING IND, DATA_PROPERTY DP
WHERE IND.RDF_RESOURCE = DP.RDF_RESOURCE
AND IND.OBJECT_TYPE_ID_INDEXED IN (........)
AND DP.PARTITION_VALUE IN (......)
AND .......
Part of Lucene indexing:
mapping.entity(DatatypeProperty.class).indexed().providedId()
.property("rdfResource",ElementType.FIELD).field().analyze(Analyze.NO).store(Store.YES)
.property("partitionValue", ElementType.FIELD).field().analyze(Analyze.NO)
mapping.entity(Indexing.class).indexed().providedId()
.property("rdfResource",ElementType.FIELD).field().analyze(Analyze.NO).store(Store.YES)
There is no association between 2 of them.
How can I translate IND.RDF_RESOURCE = DP.RDF_RESOURCE in Hibernate Search DSL???
I have blocked here for a long time, thx for helping......

Association of 4 tables in hibernate

I have 4 tables involved in this query.
Campaign - many to one business
Business - one to many client
Client - one to one contact
Contact
In contact there is the field contact_name which is unique. I need to retrieve all campaigns related to contact(via client and business) which campaign field type equals 2.
What is the best way to do it with hibernate?
In SQL is will look like this:
select *
from campaign,contact, business, client
where campaign.type=2
and client.contact_id = contact.contact_id
and contact.name = 'Josh'
and client.business_id = business.business_id
and campaign.campaign_id = business.business_id
I think that the following should work.
from Compaign where Compaign.type=2 and compaign.business.client.contact.contact_name=:name
You can execute native SQL Queries too using createSQLQuery() method of Session.
You can also use Scalar Property to avoid the overhead of using ResultSetMetadata.
You can find more information on this from here

Categories

Resources