while loop with next value - java

I want to take the key and values in the while loop
while (rs.next()) {
String simpleData = "<SimpleData name="akey">avalue</SimpleData>\n";
}
I need to take all the key and values. If I have 10 values available in resultset, then the simple data should contain all the key and values. like below
Output:- finally my string should be like below
String
simpleData = "<SimpleData name="acolumnname">acolumnvalue</SimpleData>
<SimpleData name="bcolumnname">bcolumnvalue</SimpleData>
…";
How can I achieve

If you want to create an xml structure by hand (that means without making use of a suitable library), you can try something like this:
public static void main(String[] args) {
ResultSet rs = // however you get it
// get the meta data of the result set, they are including the column headers
ResultSetMetaData resultSetMetaData = rs.getMetaData();
// and get the first column header
String columnHeader = resultSetMetaData.getColumnLabel(1);
// initialize an empty StringBuilder OUTSIDE the loop
StringBuilder sb = new StringBuilder();
// then loop through the resultset
while (rs.next()) {
// appending the results to the StringBuilder
sb.append("<SimpleData name=\"") // opening tag plus xml attribute name
.append(columnHeader) // column header as determined before the loop
.append("\">") // close the opening tag and the attribute value
.append(rs.getString(1)) // get the value from the result set
.append("</SimpleData>") // write the closing tag
.append(System.lineSeparator()); // append a line break
}
System.out.println(sb.toString());
}
This should be printing an xml structure (hopefully the desired one):
<SimpleData name="column header">value</SimpleData>
EDIT
Turned out you want to create a single xml node for each column value of a result set that has only one row. That's (nearly totally) different...
I would then access the columns by their alias (header / label) instead of their index:
public static void main(String[] args) throws SQLException {
ResultSet rs = null; // however you get it
// create a container for the headers
List<String> columnHeaders = new ArrayList<>();
// get the meta data of the result set, they are including the column headers
ResultSetMetaData resultSetMetaData = rs.getMetaData();
// determine the amount of columns
int columnCount = resultSetMetaData.getColumnCount();
// iterate them and store their values in a list of strings
for (int i = 1; i <= columnCount; i++) {
columnHeaders.add(resultSetMetaData.getColumnLabel(i));
}
// initialize an empty StringBuilder OUTSIDE the loop
StringBuilder sb = new StringBuilder();
// then loop through the resultset
while (rs.next()) {
// now loop through the columnHeaders
for (String header : columnHeaders) {
// append each column result to the StringBuilder as a single xml node
sb.append("<SimpleData name=\"") // opening tag plus xml attribute name
.append(header) // column header as determined before the loop
.append("\">") // close the opening tag and the attribute value
.append(rs.getString(header)) // get the value from the result set by header, not index
.append("</SimpleData>") // write the closing tag
.append(System.lineSeparator()); // append a line break
}
}
System.out.println(sb.toString());
}

Declare simpleData outside the while loop and in every iteration you should append to simpleData by +=
String simpleData ;
int i ;
while (rs.next()) {
simpleData += "<SimpleData name="+key+" "+rs.getString(i)+"</SimpleData>\n";
i++;
}

Related

Java/Mysql: Get all resulted lines from a stored procedure and not only the last

I have a stored procedure in mysql that returns more than one lines.
My java code to execute it is:
preparedStmt = conn.prepareCall(queryString);
preparedStmt.setString(1, String.valueOf(patient_id));
//System.out.print("select patient data java file 1 ");
boolean results = preparedStmt.execute();
int rowsAffected = 0;
// Protects against lack of SET NOCOUNT in stored procedure
while (results || rowsAffected != -1) {
if (results) {
rs = preparedStmt.getResultSet();
break;
} else {
rowsAffected = preparedStmt.getUpdateCount();
}
results = preparedStmt.getMoreResults();
}
int i = 0;
obj = new JSONObject();
while (rs.next()) {
JSONArray alist = new JSONArray();
alist.put(rs.getString("patient_id"));
alist.put(rs.getString("allergy"));
alist.put(rs.getString("allergy_description"));
alist.put(rs.getString("allergy_onset_date"));
alist.put(rs.getString("agent_description"));
alist.put(rs.getString("agent"));
alist.put(rs.getString("severity"));
obj.put("ps_allergies", alist);
i++;
}
conn.close();
At the end, ps_allergies json object contains only the last line of the query. This is the print output:
["1","week",null,"2017-07-07","vacation home","test2","mobile contact"]
I want ps_allergies to contain something similar to
[["1","hydrogen peroxide","Nuts","2017-07-04","Nursing profressionals","43","Paramedical practinioners"],["1","week",null,"2017-07-07","vacation home","test2","mobile contact"]...]
Do you know how to fix this?
Not exactly knowing what library you use, but it might have something to do with this line:
obj.put("ps_allergies", alist);
A put method in general associates the specified value with the specified key in a map. Since you are constantly overwriting you key 'ps_allergies' in the loop it will only retain the last value.
You might want to associate a list/array to ps_allergies and you then add every alist object in this list/array.
I found the solution. Instead of put I'm using append method.
obj.append("ps_allergies", alist);
The resulted output now is:
[["1","hydrogen peroxide","Nuts","2017-07-04","Nursing professionals","43","Paramedical practitioners"],["1","chlorhexidine","test123","2017-07-15","mobile contact","test232","pager"],["1","Resistance to unspecified antibiotic","Feb3","2017-03-02","mobile contact","test232","pager"],["1","week",null,"2017-07-07","vacation home","test2","mobile contact"]]

Hbase extracting value and timestamp from a cell

In hbase I have number of columns: name, city,...
Not all columns have values ( some rows can have only 'name' for example)
I want to extract all columns in a row + timestamp of column (in specific order), in case value is null I want to return empty string.
The problem that I facing, I must access column in Result by 'family' and 'qualifier' (I can't access by index of result.listCells().get(i) because null values are skipped)
scan.addColumn(Bytes.toBytes("personal data"), Bytes.toBytes("name"));
scan.addColumn(Bytes.toBytes("personal data"), Bytes.toBytes("city"));
ResultScanner scanner = table.getScanner(scan);
for (Result result = scanner.next(); result != null; result = scanner.next()){
byte [] valCity = result.getValue("personal data", "city"); //can't get timestamp using this
//check if valCity null write ("") else write the value
//next column...
}
You can try to use a CellScanner for this. See example below:
CellScanner cellScanner = result.cellScanner();
while (cellScanner.advance()) {
Cell cell = cellScanner.current();
byte[] columnName = Bytes.copy(cell.getQualifierArray(),
cell.getQualifierOffset(),
cell.getQualifierLength());
byte[] familyName = Bytes.copy(cell.getFamilyArray(),
cell.getFamilyOffset(),
cell.getFamilyLength());
long timestamp = cell.getTimestamp();
.....
}

Java - Parse delimited file and find column datatypes

Is it possible to parse a delimited file and find column datatypes? e.g
Delimited file:
Email,FirstName,DOB,Age,CreateDate
test#test1.com,Test User1,20/01/2001,24,23/02/2015 14:06:45
test#test2.com,Test User2,14/02/2001,24,23/02/2015 14:06:45
test#test3.com,Test User3,15/01/2001,24,23/02/2015 14:06:45
test#test4.com,Test User4,23/05/2001,24,23/02/2015 14:06:45
Output:
Email datatype: email
FirstName datatype: Text
DOB datatype: date
Age datatype: int
CreateDate datatype: Timestamp
The purpose of this is to read a delimited file and construct a table creation query on the fly and insert data into that table.
I tried using apache validator, I believe we need to parse the complete file in order to determine each column data type.
EDIT: The code that I've tried:
CSVReader csvReader = new CSVReader(new FileReader(fileName),',');
String[] row = null;
int[] colLength=(int[]) null;
int colCount = 0;
String[] colDataType = null;
String[] colHeaders = null;
String[] header = csvReader.readNext();
if (header != null) {
colCount = header.length;
}
colLength = new int[colCount];
colDataType = new String[colCount];
colHeaders = new String[colCount];
for (int i=0;i<colCount;i++){
colHeaders[i]=header[i];
}
int templength=0;
String tempType = null;
IntegerValidator intValidator = new IntegerValidator();
DateValidator dateValidator = new DateValidator();
TimeValidator timeValidator = new TimeValidator();
while((row = csvReader.readNext()) != null) {
for(int i=0;i<colCount;i++) {
templength = row[i].length();
colLength[i] = templength > colLength[i] ? templength : colLength[i];
if(colHeaders[i].equalsIgnoreCase("email")){
logger.info("Col "+i+" is Email");
} else if(intValidator.isValid(row[i])){
tempType="Integer";
logger.info("Col "+i+" is Integer");
} else if(timeValidator.isValid(row[i])){
tempType="Time";
logger.info("Col "+i+" is Time");
} else if(dateValidator.isValid(row[i])){
tempType="Date";
logger.info("Col "+i+" is Date");
} else {
tempType="Text";
logger.info("Col "+i+" is Text");
}
logger.info(row[i].length()+"");
}
Not sure if this is the best way of doing this, any pointers in the right direction would be of help
If you wish to write this yourself rather than use a third party library then probably the easiest mechanism is to define a regular expression for each data type and then check if all fields satisfy it. Here's some sample code to get you started (using Java 8).
public enum DataType {
DATETIME("dd/dd/dddd dd:dd:dd"),
DATE("dd/dd/dddd",
EMAIL("\\w+#\\w+"),
TEXT(".*");
private final Predicate<String> tester;
DateType(String regexp) {
tester = Pattern.compile(regexp).asPredicate();
}
public static Optional<DataType> getTypeOfField(String[] fieldValues) {
return Arrays.stream(values())
.filter(dt -> Arrays.stream(fieldValues).allMatch(dt.tester)
.findFirst();
}
}
Note that this relies on the order of the enum values (e.g. testing for datetime before date).
Yes it is possible and you do have to parse the entire file first. Have a set of rules for each data type. Iterate over every row in the column. Start of with every column having every data type and cancel of data types if a row in that column violates a rule of that data type. After iterating the column check what data type is left for the column. Eg. Lets say we have two data types integer and text... rules for integer... well it must only contain numbers 0-9 and may begin with '-'. Text can be anything.
Our column:
345
-1ab
123
The integer data type would be removed by the second row so it would be text. If row two was just -1 then you would be left with integer and text so it would be integer because text would never be removed as our rule says text can be anything... you dont have to check for text basically if you left with no other data type the answer is text. Hope this answers your question
I have slight similar kind of logic needed for my project. Searched lot but did not get right solution. For me i need to pass string object to the method that should return datatype of the obj. finally i found post from #sprinter, it looks similar to my logic but i need to pass string instead of string array.
Modified the code for my need and posted below.
public enum DataType {
DATE("dd/dd/dddd"),
EMAIL("#gmail"),
NUMBER("[0-9]+"),
STRING("^[A-Za-z0-9? ,_-]+$");
private final String regEx;
public String getRegEx() {
return regEx;
}
DataType(String regEx) {
this.regEx = regEx;
}
public static Optional<DataType> getTypeOfField(String str) {
return Arrays.stream(DataType.values())
.filter(dt -> {
return Pattern.compile(dt.getRegEx()).matcher(str).matches();
})
.findFirst();
}
}
For example:
Optional<DataType> dataType = getTypeOfField("Bharathiraja");
System.out.println(dataType);
System.out.println(dataType .get());
Output:
Optional[STRING]
STRING
Please note, regular exp pattern is vary based on requirements, so modify the pattern as per your need don't take as it is.
Happy Coding !

Combine for loop and sql in java

I have 2 input dates: myStartDate,myEndDate and a table TEST_TABLE with columns
TEST_ID, TEST_USER,TEST_START, TEST_END
I need to check if the range of dates between myStartDate and myEndDate have corresponding records in the TEST_TABLE.
I also need to ensure that I don't retrieve duplicate records.
Here's a sample of the logic I have so far:
Assuming,
myStartDate=06/06/2012;myEndDate=06/09/2012
int diff = myEndDate - myStartDate; //In this case = 3
String myQuery = "SELECT * FROM TEST_TABLE WHERE"+ myStartDate +"BETWEEN TEST_START AND TEST_END OR "+ (myStartDate +1) +" BETWEEN TEST_START AND TEST_END OR"+ (myStartDate+2)+"BETWEEN TEST_START AND TEST_END OR"+(myStartDate+3)+"BETWEEN TEST_START AND TEST_END";
List <TestTableData> myList = new List();
//Exceute query & save results into myList using add method
Want to know if there's any way to test the range of dates between myStartDate &myEndDate using a for loop in java code, instead of the approach used above in myQuery.Also, how can I avoid duplicates.
New to Java so any help would be appreciated!
Use a ResultSet to iterate over the output, like the code below.
while (res.next()) {
String col1= res.getString("col1");
String col2 = res.getString("col2");
}
If you use an Array implementation , it does not allow for duplicate elements and hence there is no need to check for one.
But if you must use a list then , you could use the following code to remove any duplicate elements.
public static void removeDuplicates(List list)
{
Set set = new HashSet();
List newList = new ArrayList();
for (Iterator iter = list.iterator(); iter.hasNext(); ) {
Object element = iter.next();
if (set.add(element))
newList.add(element);
}
list.clear();
list.addAll(newList);
}
I think what you are asking are some generic questions about how to read a database and how to handle dates in java. I will give you some sample code below. But I suggest you look at the java database tutorial http://docs.oracle.com/javase/tutorial/jdbc/index.html and the java.util.Date api doc http://docs.oracle.com/javase/1.5.0/docs/api/java/sql/Date.html for more info.
Here is some sample code that specifically demonstrates how to implement your question:
// get the input dates
// they are hard coded in this example
// but would probably normally be passed in
String startDateStr = "2/3/03";
String endDateStr = "3/1/03";
// unfortunately, there are 2 "Date" classes in this code and you need to differentiate
// java.util.Date is the standard java class for manipulating dates
// java.sql.Date is used to handle dates in the database
// name conflicts like this are rare in Java
SimpleDateFormat dateFmt = new SimpleDateFormat("M/d/yy");
java.util.Date myStartDate = dateFmt.parse(startDateStr);
java.util.Date myEndDate = dateFmt.parse(endDateStr);
// conneect to the database
// I am using mysql and its driver class is "com.mysql.jdbc.Driver"
// if using a different database, you would use its driver instead
// make sure the jar containing the driver is in your classpath (library list)
// you also have to know the url string that connects to your database
Class.forName("com.mysql.jdbc.Driver").newInstance(); // loads the driver
Connection dbConn = DriverManager.getConnection(
"jdbc:mysql://localhost/testdb", "(db user)", "(db password)"
);
// get the database rows from the db table
// my table is named "testtable"
// my columns are named "DateStart" and "DateEnd"
Statement st = dbConn.createStatement();
String sqlStr = "Select * from testtable";
ResultSet rs = st.executeQuery(sqlStr);
// loop through the rows until you find a row with the right date range
boolean foundRange = false;
while (rs.next()) {
java.util.Date dbStartDate = rs.getDate("DateStart");
java.util.Date dbEndDate = rs.getDate("DateEnd");
if (myStartDate.before(dbStartDate)) continue;
if (myEndDate.after(dbEndDate)) continue;
foundRange = true;
break;
}
if (foundRange) {
// code that executes when range is found in db
} else {
// code that executes if range not found in db
}
dbConn.close();
Hope this helps you get started.

Iterartor - How to traverse for specific records

I have executed a query using JDBC and traversing the resultset I have stored all fields in List in java.
List<String> dataList=new ArrayList<String>();
while(res.next())
{
dataList.add(res.getString(1));
dataList.add(res.getString(2));
dataList.add(res.getString(3));
dataList.add(res.getString(4));
dataList.add(res.getString(5));
dataList.add(res.getString(6));
dataList.add(res.getString(7));
}
Iterator<String> it= dataList.iterator();
As I have added directly into list so how can I get this 7 fields while traversing the iterator.
Means:
while(it.hasNext())
{
String f1=it.next();
}
Like wise everytime I want 7 fields at a time
and next 7, next 7....... so on
Using this while loop how can I get those 7 fields (one row in table having 7 field) at a time.
I get little bit confuse here. Please help me.
Thanks
What you want to do is actually create another object that stores all seven of the values.
Then create a list of these entries so that you can access one row at a time, which is what I think you are asking.
First create a class for the row.
private static class Entry {
String[] row;
public Entry ( ResultSet r ) {
row = new String [ 7 ];
for (int i = 1; i <= 7; i++) {
row[i] = r.getString(i);
}
}
}
Using that, you can then create a list of Entry objects.
List<Entry> entryList = new ArrayList <Entry> ();
while(res.next())
{
entryList.add ( new Entry ( res ) );
}
Then, you can go ahead and loop through entryList and get any specific entry you would want.
Of course, if you have specific values, it might be wise to create instance variables of type String for Entry rather than an array of Strings.
By that I mean you could do this:
private static class Entry {
String column1; // rather than name column1 use what the column semantically represents
String column2;
// ...
public Entry ( ResultSet r ) {
column1 = r.getString(1);
// ...
}
This way, you can also calls like r.getInt(i) for certain columns which have an different type other than String.
Good luck!
I think your List declaration should be
List<Any DAO Object> instead of List<String>
While fetching from resultset, create a DAO object, add all fetched data into that object and then add that object into the list.
Then you can iterate and get each DAO object at each iteration.
You can use DatabaseMetaData class,
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost/testdb";
private static final String USERNAME = "root";
private static final String PASSWORD = "";
public static void main(String[] args) throws Exception {
Class.forName(DRIVER);
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
DatabaseMetaData metadata = connection.getMetaData();
ResultSet resultSet = metadata.getColumns(null, null, "users", null);
while (resultSet.next()) {
String name = resultSet.getString("COLUMN_NAME");
String type = resultSet.getString("TYPE_NAME");
int size = resultSet.getInt("COLUMN_SIZE");
System.out.println("Column name: [" + name + "]; type: [" + type + "]; size: [" + size + "]");
}
connection.close();
}

Categories

Resources