Need to pass parameter dynamically for Excel generation - java

I am having a select query, which generate dynamically according to the number of fields that the user selects from multiple select box.
while (rs.next()) {
data.put(Integer.toString(i), new Object[] {rs.getString(1), rs.getString(2)});
i++;
}
I have created query dynamically.
Now i need to pick the values from DB using rs.getString().
Above I have given two fields manually. but in my case number fields may vary according to user selection.
so something like List reference i have to put instead of rs.getString(1), rs.getString(2).
can any one give suggestion on this.

Step1: please form your select query with selective columns based on user selection.
if the user selects col1, col2, please form query like select col1, col2 from table.
Step2: Use the ResultSetMetaData api method getColumnCount() to know the no of columns available in resultset
Step3: Based on Step2, use getXXXMethod(columnIndex) to retrieve the values.
Example:
int count = rsMetaData.getColumnCount();
while (rs.next())
{
String[] colValues = new String()[count];
for(int i=0; i<count;i++)
{
colValues[i] = rs.getString(i);
}
System.out.println("The current result set values are :"+colValues);
}

Related

Using sub queries

I am trying to access a data in a table using a sub query.
The table 1 contains a foreign key to table 2 , which means i can use that key to access the data in table 2.
My problem is after i return the array list from the below shown method , the arraylist is null.
This is what i have done:
LogEntry logBookDates;
List<LogEntry> bookList =new ArrayList();
try{
PreparedStatement getSummaryStmt=con.prepareStatement("SELECT * FROM LOGENTRYTABLE WHERE DIARYCODE =(SELECT Diarycode FROM LOGBOOKTABLE WHERE STUDENTUSERNAME=? OR SUPERVISORUSERNAME=? AND PROJECT_APPROVE_STATUS=?)");
//the above statment is the sub query which i have created, i get the diary code from log book table and then access the log entry table.
getSummaryStmt.setString(1,userName);
getSummaryStmt.setString(2,userName);
getSummaryStmt.setString(3,"Accepted");
ResultSet rs=getSummaryStmt.executeQuery();
while(rs.next())
{
logBookDates=new LogEntry(rs.getString("STUDENTUSERNAME"),rs.getString("SupervisorUsername"),rs.getString("projecttitle"),rs.getString("projectDescription"),rs.getDate("startDate"),rs.getDate("enddate"),rs.getString("project_approve_status"),rs.getString("diarycode"),rs.getString("projectcode"),rs.getInt("Index"),rs.getString("log_Entry"),rs.getDate("logentry_date"),rs.getString("supervisor_comment"),rs.getString("project_progress"));
bookList.add(logBookDates);
}
}catch(Exception e){}
return bookList;
}
I have not used sub queries before and this is the first time am using them.
What seems to be the problem here ?
Thank you for your time.
Edit : Sample data of logbook table
Sample Data of logentry table
Expected output:
I don't have a screen shot of that but what i need is just to iterate through the arraylist which will be returned from the above method.
Here is the problem, the LOGENTRYTABLE table doesn't contain a column with STUDENTUSERNAME, SupervisorUsername, projecttitle, projectDescription, startDate, etc...
rs.getString("STUDENTUSERNAME"), rs.getString("SupervisorUsername"), etc...
probably, you need JOIN query
"SELECT * FROM LOGENTRYTABLE LT
INNER JOIN LOGBOOKTABLE LB ON LT.DIARYCODE=LB.DIARYCODE
WHERE LT.DIARYCODE =
(SELECT DIARYCODE FROM LOGBOOKTABLE
WHERE (STUDENTUSERNAME=? OR SUPERVISORUSERNAME=?)
AND PROJECT_APPROVE_STATUS=?)"

How to compare list of records against database in Java?

How to compare list of records against database? I have more than 1000 records in list and need to validate against database. How to validate each record from list to database? Select all the data from database and stored in list, then have to compare the values? Please advise...
The below code lists values to validate against database.
private void validatepart(HttpServletRequest req, Vector<String> errors) {
Parts Bean = (Parts)req.getAttribute("partslist");
Vector<PartInfo> List = Bean.getPartList();
int sz = partList.size();
for (int i = 0; i < sz; i++) {
PartInfo part = (PartInfo)partList.elementAt(i);
System.out.println(part.getNumber());
System.out.println(part.getName());
}
}
This depends on what you mean by compare. If it's just one field then executing a query such as select * from parts_table where part_number = ?. It's not that much of a stretch to add more fields to that query. If nothing is returned you know it doesn't exist.
If you need to compare and know exactly which values are different then you can try something like this
List<String> compareObjects(PartInfo filePart, PartInfo dbPart) {
List<String> different = new LinkedList<String>();
if (!filePart.getNumber().equals(dbPart.getNumber())) {
different.add("number");
}
//repeat for all your fields
return different;
}
If your list of objects that you need to validate against the database includes a primary key, then you could just build a list of those primary key values and run a query like:
SELECT <PRIMARY KEY FIELD> FROM <TABLE> WHERE <PRIMARY_KEY_FIELD> IN <LIST OF PRIMARY KEYS> SORT BY <PRIMARY KEY FIELD> ASC;
Once you get that list back, you can compare the results. My instinct would be to put your data (and the query results too) into a Set object and then call removesAll() to get the items not in the database (reverse this for items in the database but not in your set):
yourDataSet.removeAll(queryResults);
This assumes that you have an equals() method implemented in your PartInfo object. You can see the Java API documentation for more details.

Get single ScrollableResults row

I am trying to extract count(*) matching certain predicates. Every time I use createSQLQuery, I find myself having to write the code along the lines of,
// skipped code
Query q = session.createSQLQuery("select count(*) from A where id=1");
Scrollable results = q.scroll();
while ( results.next() )
{
Object[] row = Object[] results.get();
// Assign it
String str = row[0];
//set and persist
}
I have many such queries unioned over a single transaction. How do I get single result here? Am I missing something?
You can use this method instead:
Object[] row = (Object[]) query.uniqueResult();
If the query returns more than one result, this method will throw an exception
EDIT:
On top of that, you could use a ResultTransformer to convert the Object[] into an Integer. This would remove the need to get the result array and then extract it's first entry. See this example for more info

Java remove duplicate values from result set

I have requirement to remove the duplicate values from result set based on some unique identifier.
I need to remove the duplicates from the result set.
while(resultSet.next())
{
int seqNo = resultSet.getInt("SEQUENCE_NO");
String tableName = resultSet.getString("TABLE_NAME");
String columnName = resultSet.getString("COLUMN_NAME");
String filter = resultSet.getString("FILTER");
}
from the above iteration, i m getting 2 rows from result set. There is same seq no,same table name, different columnname, same filter.
1 PRODUCTFEES CHARGETYPE PRODUCTID
1 PRODUCTFEES PRODUCTCODE PRODUCTID
My requirement is to remove the duplicate table name, duplicate seq no, duplicate filter.
I want to get output something below,
1 PRODUCTFEES CHARGETYPE PRODUCTCODE PRODUCTID
By the example you provide, it seems like you want to output all distinct values for each column indidivually (there are 4 columns in the table, but you output 5 values).
Being the question tagged java, an approach you could take would be using an implementation of Set for each of the columns, so that duplicates won't get through. Then output all the elements of each Set.
LinkedHashSet[] sets = new LinkedHashSet[]{
new LinkedHashSet(),
new LinkedHashSet(),
new LinkedHashSet(),
new LinkedHashSet() };
while(resultSet.next()) {
sets[0].add(resultSet.getInt("SEQUENCE_NO"));
sets[1].add(resultSet.getString("TABLE_NAME")););
sets[2].add(resultSet.getString("COLUMN_NAME"));
sets[3].add(resultSet.getString("FILTER"));
}
StringBuilder buf = new StringBuilder();
for (LinkedHashSet set : sets) {
// append to buf all elements of each set
}
But it might be simpler to address this from the very same SQL query and just make SELECT DISTINCT columnX for each of the columns and output the result without further manipulation. Or use an aggregation function that will concatenate all distinct values. The implementation will be highly dependent on the DBMS you're using (GROUP_CONCAT for MySQL, LISTAGG for Oracle, ...). This would be a similar question for Oracle: How to use Oracle's LISTAGG function with a unique filter?
Based on the different outputs I'd say, that you not just need to remove duplicates, but also reorder the data from the duplicates.
In that case you need to fill a new data-array (or similar structure) in the while(resultSet.next()), and after that loop over the newly arranged data-object and output accordingly.
In Meta-Lang this would be as follows:
while resultset.next()
if newdata-array has unique key
add column-name to found entry in newdata-array
else
create new entry in newdata-array with column-name
while newdata-array.next()
output seq, table-name
while entry.column-names.next()
output column-name
output product-id

Any better approach rather than result.getString() while iterating a result set in java

I have 6 columns in a table. I have a select query which selects some records from the table. While iterating over the result set, im using the following logic to extract the values in the columns:
Statement select = conn.createStatement();
ResultSet result = select.executeQuery
("SELECT * FROM D724933.ECOCHECKS WHERE ECO = '"+localeco+"' AND CHK_TOOL = '"+checknames[i]+"'");
while(result.next()) { // process results one row at a time
String eco = result.getString(1);
mapp2.put("ECO", eco);
String chktool = result.getString(2);
mapp2.put("CHECK_TOOL", chktool);
String lastchktime = result.getString(3);
mapp2.put("LAST_CHECK_TIME", lastchktime);
String status = result.getString(4);
mapp2.put("STATUS", status);
String statcmts = result.getString(5);
mapp2.put("STATUS_COMMENTS", statcmts);
String details = result.getString(6);
mapp2.put("DETAILS_FILE", details);
}
I have 2 questions here:
1. Is there any better approach rather than using result.getString()???
2. Lets say, another column gets added to the table at a later point. Is there any way my code handles this new addition without making change to the code at that point of time
You can use ResultSetMetaData to determine the number and names of the columns in your ResultSet and deal with it this way. Note however that changing the number of columns in the database - affecting your code - and having the code still work may not always be a good idea.
Additionally, note that you're overwriting the values in your map on each iteration of the loop. You probably want to add those maps to some sort of List?
Finally, you need to make sure that your getString methods will not return null anywhere, otherwise putting it into a map will throw an exception.
Statement select = conn.createStatement();
ResultSet result = select.executeQuery("SELECT * FROM D724933.ECOCHECKS WHERE ECO = '"+localeco+"' AND CHK_TOOL = '"+checknames[i]+"'");
ResultSetMetaData rsmd = result.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
List data = new ArrayList<Map>();
Map mapp2;
while(result.next()) { // process results one row at a time
mapp2 = new HashMap<String, String>();
for(int i=1; i<=numberOfColumns; i++) {
mapp2.put(rsmd.getColumnName(i), rs.getString(i));
}
data.add(mapp2);
}
Each of the get family of methods on ResultSet has an overloaded variant that takes a column name as argument. You can use this instead to reduce reliance on ordering of columns.
ResultSet results = ...;
results.getString(1);
You could do this:
results.getString("name");
But the preferred way of handling this sort of problem is to impose an ordering of your own on the result set, by explicitly selecting the columns you want in the initial query.
If your table adds a new column, then obviously you have to change your code, because in your code you use hardcoded value, I mean getString(1).
Instead use ResultSetMetaData's getColumnCount and do some other logic to get that many column values dynamically.
Another thing for your first question, ResultSet contains getXXX() methods with two types of parameters, String column name and int column index. You used the index instead of column name which will perform little faster.
It is bad practice to use SELECT *, instead you should select only the columns you are interested in. The reason is exactly what you mentioned: What happens if your DB changes. you don't want to go trhough the whole code and find and edit all SELECT * statements.
You don't need to put the result into your own map because you can already do:
result.getString("DETAILS_FILE");
But there are already other answers explaining that.
It would be further helpful to use a constant instead of the string "DETAILS_FILE". You can use the constant in the SELECT and in the result.getString(). In case your DB changes you only need to introduce a new constant or change an existing one.

Categories

Resources