How to get data from DB using query param? - java

My DB data is
-----------------------
id | value |
-----------------------
1 | a,b |
-----------------------
2 | c |
-----------------------
3 | d |
-----------------------
I am trying to get DB values using this endpoint: http://localhost:8996/abc/v2/tpids?values=a,b...
String[] tpids = apiData.request.getParam(constants.tpids).split(",")
abc/v2/tpids?values=a,b,c,d this case was failed... it treated a,b,c,d as comma separated values –
In this case, a and b as treated two different values
but I need [a,b] as treated single value... How to escape comma form param value... Thanks

It seems like the splitting is redundant, and you just need to treat the entire input as a single string:
String tpids = apiData.request.getParam(constants.tpids);

Related

How to call postgresql function that returns TABLE type from Java code?

I have a postgresql function with this signature...
create function getProductsPerCodes(p_c_prodcodes VARCHAR(1000))
RETURNS
table (prodcode VARCHAR(1000), prodname VARCHAR(1000), prodline VARCHAR(1000), prodvendor VARCHAR(1000), quantity_in_stock int)
AS
The function returns TABLE type.
From SQL client, I can call this function like this:
select getProductsPerCodes('''c1'',''c4'',') rec
It prints the records fine.
Now, how do I call this function from Java code and access the data returned by the function?
I need to access the table records and access all the fields that constitute the table record.
You should to use "table context syntax"
SELECT * FROM getProductsPerCodes($$'c1','c4',$$)
When your string contains quotes ', you can use Postgres' custom string separators like $$ in example. Then you don't need to double quotes and code can be more readable.
Handling the result of a set returning function is no different than handling the result of a regular select * from some_table command.
But you should not pass parameters as part of the SQL string. Use a PreparedStatement instead:
PreparedStatement pstmt = connection.prepareStatement("select * from getproductspercode(?,?)");
pstmt.setString(1, "c1");
pstmt.setString(2, "c4");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
String code = rs.getString("prodcode");
String name = rs.getString("prodname");
...
int stock = rs.getInt("quantity_in_stock");
}
I put together a small demo to reinforce the statement by #a_horse_with_no_name that "set returning function is no different than handling the result of a regular select." This demo defines and populates a small table sort on mimicking yours. It contains 2 TABLE returning functions. It then runs a standard query and each of the functions, all with the same parameters. Ad you can see they produce identical results. (I used comma separated list :( instead of 2 parameters as you have. Did not have to deal with nested quotes. (And I initially misread your parameter list and did not want to redo them.).
I then ran one of them with different parameter values, (c3,c1). It produced the following:
+----------------+-------------+--------------+
| pc_name | pc_code_set | pc_code_grp |
+----------------+-------------+--------------+
| Test col n= 01 | c1 | Group Low |
| Test col n= 03 | c3 | Group Low |
| Test col n= 06 | c1 | Group Medium |
| Test col n= 08 | c3 | Group High |
| Test col n= 11 | c1 | Group High |
| Test col n= 13 | c3 | Group High |
+----------------+-------------+--------------+
But which one was run, you cannot tell. So here a test for you. Build them in your environment and give each a try. You will need to change what is called, but not handling the result.

Write Spring Specification to filter unrelated tables

I am working on a project Spring and Java, generated using JHipster. I want to filter on table that doesn't have a direct relationship with another.
My purpose is almost asked in a previous similar question
Write Spring Specification with multiple inner join & other conditions
But in my case , I ve two unrelated entities :
Consultant (id : Long , FullName : string , profileRank : Enum of string )
Rank (id : Long , level : Enum of string , rate : Double )
Consultant | Rank
|
id | FullName | profileRank | id | level | rate
1 | aaaaa | 'ONE' | 1 | 'ONE' | 1
2 | bbbbbb | 'THREE' | 2 | 'TWO' | 2
3 | cccccc | 'FOUR' | 3 | 'THREE' | 3
4 | dddddd | 'THREE' | 4 | 'FOUR' | 4
I want to filter consultant list by rate using level
Example : get consultants with rate greater than 3
Expected result
id | FullName | profileRank
3 | cccccc | 'FOUR'
I ve searched in documentation and many articles without get it to work please how to achieve that .
You don't need to write a specification for your case.
Fetch all the ranks with levels and rates
Filter these values and keep only the ones greater than 3 (step 1 and 2 can be combined). The result will be a List<Rank> that contains only FOUR rank
list.stream(rank => rank.level).collect(toList())
The result of step 3 will be passed to a repository method like List<Consultant> findByProfileRankIn(List<String> levelNames)
Another alternative would be joins something like this Joining tables without relation using JPA criteria
If you still want a spec that's also possible. Spring Data Join with Specifications

How to format data in column for WHERE clause just before executing SELECT?

I am using Microsoft SQL Server with already stored data.
In one of my tables I can find data like:
+--------+------------+
| id | value |
+--------+------------+
| 1 | 12-34 |
| 2 | 5678 |
| 3 | 1-23-4 |
+--------+------------+
I realized that the VALUE column was not properly formatted when inserted.
What I am trying to achieve is to get id by given value:
SELECT d.id FROM data d WHERE d.value = '1234';
Is there any way to format data in column just before SELECT clause?
Should I create new view and modify column in that view or maybe use complicated REGEX to get only digits (with LIKE comparator)?
P.S. I manage database in Jakarta EE project using Hibernate.
P.S.2. I am not able to modify stored data.
One method is to use replace() before the comparison:
WHERE REPLACE(d.value, '-', '') = '1234'

Obtaining the primary key from an inserted DataSet to chain into other insertions

Suppose I have the following tables, in an Oracle DB
Foo:
+--------+---------+---------+
| id_foo | string1 | string2 |
+--------+---------+---------+
| 1 | foo | bar |
| 2 | baz | bat |
+--------+---------+---------+
Bar:
+--------+-----------+--------+
| id_bar | id_foo_fk | string |
+--------+-----------+--------+
| 1 | 1 | boo |
| 2 | 1 | bum |
+--------+-----------+--------+
When I insert into Foo, by using a Dataset and JDBC, such as
Dataset<Row> fooDataset = //Dataset is initialized
fooDataset.write().mode(SaveMode.Append).jdbc(url, table, properties)
an ID is auto-generated by the database. Now when I need to save Bar, using the same strategy, I want to be able to link it to Foo, via id_foo_fk.
I looked into some possibilities, such as using monotonically_increasing_id() as suggested in this question, but it won't solve the issue, as I need the ID generated by the database. I tried what was suggested in this question, but it leads to the same issue, of unique non-database IDs
It's also not possible to select from the JDBC again, as string1 and string2 may not be unique. Nor is it possible to change the database. For instance, I can't change it to be UUID, and I can't add a trigger for it. It's a legacy database that we can only use
How can I achieve this? Is this possible with Apache Spark?
I'm not a Java specialist so you will have to look into the database layer on how to proceed exactly but there are 3 ways you can do this:
You can create a store procedure if the database server you are using is capable of (most do) and call it from your code.
Create a trigger that returns the id number on the first insertion and use it in your next DB insertion.
Use UUID and use this as the key instead of the database auto generated key.

Spring Data with strict In-clause

See updated question below
I want to query for elements where every element is required to have all given attributes of e.g. a set to be returned, not only one.
Default Spring Data Jpa Query, where one attribute is enough:
findAllByAttributeIn(Set<Attribute> setAttr)
Example problem
For these elements (abstracted, no actual table)
id | attr
----------
1 | A
2 | A,B
3 | A,B,C
with this filter:
setAttr: [A,B]
the default query
findAllByAttributeIn(Set<Attribute> setAttr)
returns all elements (by ids):
[1,2,3]
Desired result is only the second element (with [A,B]).
Is that possible with the given Spring Data Jpa query keywords or is the only solution to create a custom query?
Updated question:
There are two entities, Media and Tag. They have a many-to-many relationship which is realised in the table Media_has_tags. Every media can have any number of tags (0..*). So in my Spring app, media has a set of tags as an attribute and vice versa. The classes:
Media = {
id: string,
Set<Tag> tags,
...
}
Tag = {
id: string,
Set<Media> medias,
...
}
The corresponding tables are:
Media
-------
id | ...
Tag
-------
id | ...
title | ...
Media_has_tags
-------
media_id | tag_id
And now I have a set of tags with which I want to get all medias which have every tag of that set. They can have more tags of course, but they need to have every tag of the set I am providing.
Concrete example:
Media
-------
id | ...
-------
1 |
2 |
Tag
-------
id | title | ...
1 | A |
2 | B |
Media_has_tags
-------
media_id | tag_id
1 | 1
2 | 1
2 | 2
Given a set of tags [A, B] I want only media with id 2 as a result since media with id 1 doesn't have tag 'B'.
Can I achieve that with Keywords and if, how or do I have to build my own query?
Sorry, but your question is incorrect initially.
findAllByAttributeIn(Set<Attribute> setAttr)
produces an SQL request like this:
select * from <table_name> t where t.attribute in (?,?,?...?)
So according to RDBMS-rules your result is correct and expectable.
What is a real structure for your abstract tables?
id | attr
----------
1 | A
2 | A,B
3 | A,B,C
In real life it would be somethink like this:
id | attr
----------
1 | A
2 | A
2 | B
3 | A
3 | B
3 | C
And again - in this case the result you have got is ok for any RDBMS.
Give us real examples from your project, please
Update because of question update:
OK, the problem has been clarified.
In this case there is no straight way to solve it using standard CrudRepository syntax. But you can try to write #Query request to manage to get the goal.
In a clear SQL this problem has to be solved by using group by together with having. It would be something like this:
select media_id
From media_has_tags
Where tag_id in(1,2 3)
Group by media_id
Having count(*)=3
In terms of SpringData it means that you have to create MediaHasTagsRepository interface and an appropriate query method to get looked ids. After that you can easily find medias you're looking for.
But this approach is not looking good IMHO. The best way I suppose is to find all the medias by the your initial query and than filter them by the given condition in Java.
E.g. you have a List<Media> where each element has an least a one tag that you are looking for. Then we can do a loop to find medias that contains all the looked tags:
List<Media> list; // here is a filled list of medias
Set<String> titles; // here is a set of title interseptions we a looking for
final List<Media> result = new ArrayList<>();
for (Media media: list) {
if (!list.getTags().isEmpty()){
Set<String> tagTitles = list.getTags().stream().map(item -> item.getTitle()).filter(title -> titles.contains(title)).distinct().collect(Collectors.toSet());
if (tagTitles.size() == titles.size()) {
result.add(media);
}
}
}

Categories