Below you can find the code that I'm using to retrieve a table from a generic SQL statement (the SQL code is inputed by the user in another part of the code).
Since I'll be storing more than one table in the future, and the retrieved table will have some format functions applied to it, I'm storing the values in a:
Map<String, Map<String,List<Object>>> tables = new HashMap<String, Map<String,List<Object>>>();
The first Map is a Table, the second is a Column and finally the list hold each line of data.
The column names/order in:
Map<String, TreeMap<Integer, String>> order = new HashMap<String, TreeMap<Integer, String>>();
The Map is tha table, the TreeMap are the column number - column name
The code to create de generic table is:
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
for(int i = 1; i <= rsmd.getColumnCount(); i++){
String name = rsmd.getColumnLabel(i); //Label vs name. Label is also what's defined by the user in: "as VENDA"
answer.put(name, null);
singleOrder.put(i, name);
}
while(rs.next()){
Iterator answerIt = answer.entrySet().iterator();
while (answerIt.hasNext()) { //Get Columns in index order to compare with body HashMap (unordered)
Map.Entry columnNameValue = (Map.Entry)answerIt.next(); //key = columnName, value = List
String columnName = (String) columnNameValue.getKey();
List<Object> tmp = answer.get(columnName);
if (tmp == null) {
tmp = new ArrayList<Object>();
answer.put(columnName, tmp);
}
Object item = rs.getObject(columnName);
if(item instanceof Integer){
item = ((Integer) item).doubleValue();
} else if (item instanceof Long){
item = ((Long) item).doubleValue();
} else if (item instanceof BigDecimal){
item = ((BigDecimal) item).doubleValue();
}
tmp.add(item);
}
}
Efficiency will be key for this part of my code. How can I improve the table creation?
(I think this is a important question for Java coders, so a clear response can serve a pattern for future programmers that have the same difficulty that I'm having now)
Update 1:
Why I'm asking: I couldn't find any example of how to handle a flexible query in Java. I've created my own solution, but I fear it's some kind of monster compared to how to handle such a case properly in Java.
As example:
Lets say I'll name the result of a first query as "table1".
The query will be: Select STORE, SALES, GOAL, EXTRA from ... ;
The order variable will be like:
Map<String, TreeMap<Integer, String>> order = new HashMap<String, TreeMap<Integer, String>>();
table1,
1, "STORE"
2, "SALES"
3, "GOAL"
4, "EXTRA"
The tables variable:
Map<String, Map<String,List<Object>>> tables = new HashMap<String, Map<String,List<Object>>>();
"table1",
"STORE",
"unit1"
"unit2"
"unit3"
"unit4"
"SALES",
1312
126
1361
6823
"GOAL"
1300
160
1200
6000
"EXTRA"
"info1"
"info2"
"info3"
"info4"
Related
I have created a table in my local dynamoDB. The fields are,
id (N)
name (S)
school (S)
classname (S)
Now I want to retrieve all the records for which school equals to "xschool" and print.
Tried the below code but it gives me an error in the query,
QuerySpec spec = new QuerySpec().withProjectionExpression("sid, classname, school")
.withKeyConditionExpression("school = :v_school").
withValueMap(new ValueMap().withString(":v_school", "abcschool"));
ItemCollection<QueryOutcome> items = table.query(spec);
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}
Any suggestions for this as I'm new to dynamoDB.
AmazonDynamoDB dynamoDBClient = createClient();
DynamoDB dynamoDB = new DynamoDB(dynamoDBClient);
String tableName = "student";
Table table = dynamoDB.getTable(tableName);
Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":sc", schoolname);
ItemCollection<ScanOutcome> items = table.scan("school = :sc", // FilterExpression
"sid, school, firstname, classname", // ProjectionExpression
null, // ExpressionAttributeNames - not used in this example
expressionAttributeValues);
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}
Try this, I think this will work for you
From the DynamoDB documentation:
The Query operation enables you to query a table or a secondary index. You must provide a partition key value and an equality condition.
The error message you got means that school is not the partition key of your table. To fix this you can
change the table definition so that school is the partition key or
use a scan instead of a query.
My issue is that I am getting the results of only one row, that also three times. I want to retrieve all the data which has stock less than 10. How do I add the object data to the arraylist?
String lowStock = "SELECT MedcineID, MName, Quantity FROM medcineinventory WHERE Quantity < :stock";
SQLQuery query = session.createSQLQuery(lowStock);
query.setParameter("stock", 10);
List<Object[]> stocks = query.list();
ArrayList<Inventory> allResults = new ArrayList<Inventory>();
Inventory iv = new Inventory();
for(Object[] data : stocks){
iv.setMedcineID((Integer) data[0]);
iv.setMName((String) data[1]);
iv.setQuantity((Integer)data[2]);
allResults.add(iv);
}
tx.commit();
session.close();
return allResults;
You have to move your Inventory iv = new Inventory(); inside the loop:
for(Object[] data : stocks){
Inventory iv = new Inventory();
iv.setMedcineID((Integer) data[0]);
iv.setMName((String) data[1]);
iv.setQuantity((Integer)data[2]);
allResults.add(iv);
}
That's because every time you go through the list of results you alter the data of the initial iv and add a new entry to the result list. So in the end you have three entries in your final list with the same values which represent the last element of the retrieved data.
Moving the creation of iv inside the loop creates new elements every time.
for(Object[] data : stocks){
Inventory iv = new Inventory();
iv.setMedcineID((Integer) data[0]);
iv.setMName((String) data[1]);
iv.setQuantity((Integer)data[2]);
allResults.add(iv);
}
Create a new inventory object inside the for loop and add that to your arraylist. Replace your for loop with this
Actually I retrieve data from database which is surely in the form of table. I want to manage data (table) in hash-map in specific format. Firstly I show you the following code and it's output in a console:
Code:
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (resultSet.next()) {
for (int i = 1; i <= columnsNumber; i++) {
if (i > 1) System.out.print(", ");
String columnValue = resultSet.getString(i);
System.out.print(columnValue );
}
System.out.println("");
}
Output:
ID SkillGroup
47010, EN.SG
47013, shabber_hassan
47014, CAM.SG
47014, CIM.SG
47014, EN.SG
47014, JZskillGroup
47014, camp_agent.SG
999, EN.SG
3333, absaara_test2.SG
3333, absaara_test3.SG
I want to make a Hasp-Map which should be filled with following way:
Key: Should be the ID.
Value: All the skillgroup (maybe in Arraylist) related to one ID
How I Can Do This:
ID ---> [All skill group related to associated ID]
47010 ---> [EN.SG]
47013 ---> [shabber_hassan,]
47014 ---> [CAM.SG,CIM.SG,EN.SG,JZskillGroup,camp_agent.SG]
999 ---> [EN.SG]
333 ---> [ab_test2.SG,ab_test3.SG]
Some help would be apppreciated !!
Use a HashMap<Integer,List<String>>.
Assuming your table has two columns (ID and Skill Group), based on your output :
Map<Integer,List<String>> map = new HashMap<>();
while (resultSet.next()) {
String key = resultSet.getInt(1);
String value = resultSet.getString(2);
List<String> values = map.get(key);
if (values == null) {
values = new ArrayList<String>();
map.put(key,values);
}
values.add(value);
}
I want to create a list with my database field values.
There are 2 columns, name and surname.
I want to create a list that stores all names in name column in a field and then add to my DTO.
Is this possible?
Steps you can follow: -
First you need to have a List<String> that will store all your names. Declare it like this: -
List<String> nameList = new ArrayList<String>();
Now, you have all the records fetched and stored in ResultSet. So I assume that you can iterate over ResultSet and get each values from it. You need to use ResultSet#getString to fetch the name.
Now, each time you fetch one record, get the name field and add it to your list.
while(resultSet.next()) {
nameList.add(resultSet.getString("name"));
}
Now, since you haven't given enough information about your DTO, so that part you need to find out, how to add this ArrayList to your DTO.
The above list only contains name and not surname as you wanted only name. But if you want both, you need to create a custom DTO (FullName), that
contains name and surname as fields. And instantiate it from
every ResultSet and add it to the List<FullName>
JDBC unfortunately doesn't offer any ways to conveniently do this in a one-liner. But there are other APIs, such as jOOQ (disclaimer: I work for the company behind jOOQ):
List<DTO> list =
DSL.using(connection)
.fetch("SELECT first_name, last_name FROM table")
.into(DTO.class);
Or Spring JDBC
List<DTO> list =
new JdbcTemplate(new SingleConnectionDataSource(connection, true))
.query("SELECT first_name, last_name FROM table", (rs, rowNum) ->
new DTO(rs.getString(1), rs.getString(2));
Or Apache DbUtils:
List<DTO> list =
new QueryRunner()
.query(connection,
"SELECT first_name, last_name FROM table",
new ArrayListHandler())
.stream()
.map(array -> new DTO((String) array[0], (String) array[1]))
.collect(Collectors.toList());
I've used Java 8 for the Spring JDBC / Apache DbUtils examples, but it can be done with older versions of Java as well.
It is. What have you tried ?
To access the database, you need to use JDBC and execute a query, giving you a ResultSet.
I would create an class called FullName with 2 String fields name and surname. Just populate these in a loop using
rs.getString("NAME"); // column name
rs.getString("SURNAME");
e.g.
List<FullName> fullnames = new ArrayList<FullName>();
while (rs.next()) {
fullnames.add(new FullName(rs));
}
Note that I'm populating the object via the ResultSet object directly. You may choose instead to implement a constructor taking the 2 name fields.
Note also that I'm creating a Fullname object. So the firstname/surname are kept separate and you have the freedom to add initials etc. later. You may prefer to rename this Person and that will give you the freedom to add additional attributes going forwards.
What worked for me is:
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
ArrayList<String> resultList= new ArrayList<>(columnCount);
while (rs.next()) {
int i = 1;
while(i <= columnCount) {
resultList.add(rs.getString(i++));
}
}
return resultList;
This worked for me->
private List<Object[]> convertResultsetToObject(ResultSet rs) throws SQLException {
List<Object[]> results = new ArrayList<Object[]>();
int count = 0;
if(rs != null) {
ResultSetMetaData rsm = rs.getMetaData();
count = rsm.getColumnCount();
}
while(rs != null && rs.next()) {
Object [] obj = new Object[count];
int temp = 1;
while(temp <= count) {
obj[temp - 1] = rs.getObject(temp);
temp++;
}
results.add(obj);
}
return results;
}
I have several tables. I have a query also. My problem is to generate the SQL query dynamically using Java.
I have the following fields in a separate table:
Collumn name status
po_number, Y
unit_cost, Y
placed_date , Y
date_closed, Y
scheduled_arrival_date Y
date_closed Y
order_quantity Y
roll_number N
product_sku N
product_category_name N
rec_vendor_quantity Y
vendor_name Y
et_conversion_unit_quantity Y
from which i have to generate a query when the status is Y, the problem here is some time the above columns
The following query is the out put of the above :
here i have inculded all the columns but i have to exculde the column which has the status of N, please help me to construt the query using java.
select
pi.po_number,poi.unit_cost,pi.placed_date CreateDate,
case when isnull(pi.date_closed) then pi.scheduled_arrival_date
else pi.date_closed end as ReceviedDate,
poi.order_quantity,poi.roll_number,p.product_sku product_name,
pc.product_category_name,poi.rec_vendor_quantity,pv.vendor_name,p.et_conversion_unit_quantity,pi.note
from
purchase_order as pi,
purchase_order_inventory as poi,
product_vendors as pv,
products AS p,
product_categories AS pc
where
pi.purchase_order_id=poi.purchase_order_id and
pc.product_category_id=p.product_category_id and
poi.product_id = p.product_id and
poi.product_category_id=pc.product_category_id and
pi.vendor_id=pv.product_vendor_id and
( ( pi.date_closed >= '2012-01-01' and pi.date_closed <='2012-09-05 23:59:59' )
or ( pi.scheduled_arrival_date >= '2012-01-01' and pi.scheduled_arrival_date <='2012-09-05 23:59:59') ) and
pi.po_type=0
and pi.status_id = 0 and poi.transaction_type = 0
order by pi.po_number
UPDATE :
QUERY : STEP 1:
SELECT rcm.id,rcm.tablename,rcm.columnname,rcm.size,rcm.displayorder,rcm.isactive FROM report_customise_master rcm where rcm.tablename !='employee' and rcm.isactive='Y' order by rcm.displayorder;
STEP 2 :
Java method to construct the query :
public Map getComplexReportQuery() {
String query = "SELECT rcm.id,rcm.tablename,rcm.columnname,rcm.size,rcm.displayorder,rcm.isactive FROM report_customise_master rcm where rcm.tablename !='employee' and rcm.isactive='Y' order by rcm.displayorder;";
String tableName = "", from = "", select = "";
StringBuffer sb = new StringBuffer();
Map<String, List<String>> resultsMap = new LinkedHashMap<String, List<String>>();
Map<String, String> displayOrderMap = new LinkedHashMap<String, String>();
Map queryMap = new LinkedHashMap();
if (!query.isEmpty() || query.length() > 0) {
sb.append(query);
}
Connection connection = getConnection();
if (connection != null) {
try {
PreparedStatement reportQueryPS = connection.prepareStatement(sb.toString());
ResultSet reportQuery_rst = reportQueryPS.executeQuery();
List<String> tables = new ArrayList<String>();;
if (reportQuery_rst != null) {
StringBuilder selectQuery = new StringBuilder(" SELECT ");
StringBuilder fromQuery = new StringBuilder(" FROM ");
while (reportQuery_rst.next()) {
tableName = reportQuery_rst.getString("tablename");
List<String> columns = resultsMap.get(tableName);
if (columns == null) {
columns = new ArrayList<String>();
resultsMap.put(tableName, columns);
}
columns = resultsMap.get(tableName);
String columnName = reportQuery_rst.getString("columnname");
columns.add(columnName);
}
tableName = "";
for (Entry<String, List<String>> resultEntry : resultsMap.entrySet()) {
tableName = resultEntry.getKey();
List<String> columns = resultEntry.getValue();
int i = 0;
for (String column : columns) {
selectQuery.append(tableName + "." + column);
if (i != columns.size()) {
selectQuery.append(",");
} else {
selectQuery.append("");
}
i++;
}
if (!tables.contains(tableName)) {
tables.add(tableName);
}
}
//to remove comma at the end of line
select = selectQuery.toString().replaceAll(",$", "");
tableName = "";
int i = 0;
for (String table : tables) {
fromQuery.append(table);
fromQuery.append(" ");
fromQuery.append(table);
if (i != tables.size()) {
fromQuery.append(",");
} else {
fromQuery.append("");
}
i++;
}
from = fromQuery.toString().replaceAll(",$", "");
queryMap.put("query", select + from);
}
//from = from+"ORDER BY "+orderbyColumn+" "+sort+" ";
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
closeConnection(connection, null, null);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} else {
System.out.println("Connection not Established. Please Contact Vendor");
}
return queryMap;// return the map/ list which contains query and sory and display order
}
STEP 3 : Result query
{query= SELECT purchase_order.po_number,purchase_order.placed_date,purchase_order.date_closed,purchase_order.scheduled_arrival_date,purchase_order_inventory.unit_cost,purchase_order_inventory.order_quantity,purchase_order_inventory.roll_number,purchase_order_inventory.rec_vendor_quantity,products.product_sku,products.et_conversion_unit_quantity,product_categories.product_category_name ,product_vendors.vendor_name FROM purchase_order purchase_order,purchase_order_inventory purchase_order_inventory,products products,product_categories product_categories,product_vendors product_vendors}
but this not what i wanted, Please help me to construct the query i have given.
Two queries
You need to make two queries:
Query which fields are enabled
Build the second query string (the one you want to build dinamically)
It's this way because a SQL query has to tell which columns will be included before querying any data. In fact it will be used to build the internal DB query plan, it is, the way the DB motor will use to retrieve and organize the data you ask.
Query all columns
Is it necesary to query only that fields? Can't you query everything and use the relevant data?
Joins
Looking at the updated question I guess you need to dynamically add where conditions to join tables correctly. What I should do is have a reference telling me what coindition to add when a table is present.
There are at least two options:
Based on table pairs present (by example: "if A and B are present then add A.col1 = B.col2")
Based on tables present ("if B is present, then add A.col1 = B.col2; A should be present"
Based on your example I think the second option is more suitable (and easy to implement).
So I should have some static Map<String, JoinInfo> where JoinInfo has at least:
JoinInfo
+ conditionToAdd // by example "A.col1 = B.col2"
+ dependsOnTable // by example "A" to indicate that A must be present when B is present
So you can use:
that info to add tables that should be (by example: even if A has no selected cols, must be present to join with B)
include the conditionToAdd to the where clause
Anyway... I think you are getting into much trouble. Why so dynamic?
You have to approach the thing step by step.
Firstly you have to create a query that will return all rows that have status='Y'
Then you will put the COLUMN_NAME in a list of Strings.
List<String> list = new List<String>();
while(rs.next()){
list.add(rs.getString(columnNumber));
}
And then you have to loop the List and generate dynamically your second sql statement
String sqlSelect = "SELECT ";
String sqlFrom = " FROM SOME_OTHER_TABLE "
String sqlWhere = " WHERE SOME_CONDITION = 'SOME_VALUE' "
for(String x : list){
sqlFrom += x +" , "+;
}
//here make sure that you remove the last comma from sqlFrom because you will get an SQLException
String finalSql = sqlSelect + sqlFrom + sqlWhere ;