Retrieve data duplication error - java

What i am trying to do:
Do 2 rounds of validation to retrieve the data from MySQL, first is to check the time of the day, second to check if that timing is taken, if the timing is not taken i take the data from that row and add it into an arraylist.
Problems:
My logic for this is that i run the loop while(rs.next()), i will do my first round of checking which is to check the timing, after that when the checking passes it goes into another if, and when that passes the check it will get that data from that row and add it into arraylist. However when i run the code, i believe the checking is working BUT it stores the same data over and over again into the arraylist. and in particular it is storing the last row's data, for example where id 1,2,3,4,5,6 passes the validation it will just store id6 over and over again.
try {
PreparedStatement stmt = so.getPreparedStatementWithKey("SELECT * FROM et_elderly WHERE room = ?");
stmt.setString(1, roomNum);
stmt.executeQuery();
rs = stmt.getResultSet();
while(rs.next()){
if(dosageTime.equalsIgnoreCase("morning")){
if(rs.getInt("morningtaken")==0){
// calculate the age
java.sql.Date reportDate=rs.getDate("dob");
DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
String text = df.format(reportDate);
String year=text.substring(0, 4);
String month=text.substring(5,7);
String day=text.substring(8,10);
// setting the information
data.setElderBed(rs.getInt("bed"));
data.setElderName(rs.getString("name"));
data.setElderAge(ElderData.getAge(year,month,day));
data.setElderGender(rs.getString("gender"));
DosageList.add(data);
numofElder++;
}
}
else if (dosageTime.equalsIgnoreCase("afternoon")){
if(rs.getInt("afternoontaken")==0){
// calculate the age
java.sql.Date reportDate=rs.getDate("dob");
DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
String text = df.format(reportDate);
String year=text.substring(0, 4);
String month=text.substring(5,7);
String day=text.substring(8,10);
// setting the information
data.setElderBed(rs.getInt("bed"));
data.setElderName(rs.getString("name"));
data.setElderAge(ElderData.getAge(year,month,day));
data.setElderGender(rs.getString("gender"));
DosageList.add(data);
numofElder++;
}
}
else if (dosageTime.equalsIgnoreCase("noon")){
if(rs.getInt("noontaken")==0){
// calculate the age
java.sql.Date reportDate=rs.getDate("dob");
DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
String text = df.format(reportDate);
String year=text.substring(0, 4);
String month=text.substring(5,7);
String day=text.substring(8,10);
// setting the information
data.setElderBed(rs.getInt("bed"));
data.setElderName(rs.getString("name"));
data.setElderAge(ElderData.getAge(year,month,day));
data.setElderGender(rs.getString("gender"));
DosageList.add(data);
numofElder++;
}
}
}
} catch (SQLException e1) {
e1.printStackTrace();
}

You're using a single instance of data which is simply updated on each iteration of the ResultSet...
while(rs.next()){
if(dosageTime.equalsIgnoreCase("morning")){
if(rs.getInt("morningtaken")==0){
//...
// You never create a new "data" object...
// setting the information
data.setElderBed(rs.getInt("bed"));
data.setElderName(rs.getString("name"));
data.setElderAge(ElderData.getAge(year,month,day));
data.setElderGender(rs.getString("gender"));
DosageList.add(data);
numofElder++;
}
}
So, basically, you're only going to end up with a List of objects which are all the same object. You could test using a Set of some kind and you'd end up with a single item in your Set.
Instead, you might want to consider using a Factory or Builder pattern to ensure that on each iteration through the ResultSet, you are creating a new instance of data filled with the properties from the database

Related

How to get data from SQL with sql2o?

I'm trying to get data from mySQL to List in java using sql2o lib.
But for some reason I just fail to understand how to use it properly (it looks like).
Here is the faulty code:
List<String> returning = new ArrayList<String>();
String date = "";
String playerList = "";
String playerCount = "";
String playerMax = "";
con.createQuery(sql)
.throwOnMappingFailure(true).addColumnMapping("date", date)
.addColumnMapping("playerList", playerList)
.addColumnMapping("playerCount", playerCount)
.addColumnMapping("playerMax", playerMax).executeAndFetch(String.class);
returning.add(date);
returning.add(playerList);
returning.add(playerCount);
returning.add(playerMax);
And here is error I get:
org.sql2o.Sql2oException: Could not map date to any property.
at org.sql2o.DefaultResultSetHandlerFactory.newResultSetHandler0(DefaultResultSetHandlerFactory.java:199)
at org.sql2o.DefaultResultSetHandlerFactory.access$200(DefaultResultSetHandlerFactory.java:17)
at org.sql2o.DefaultResultSetHandlerFactory$5.evaluate(DefaultResultSetHandlerFactory.java:160)
at org.sql2o.DefaultResultSetHandlerFactory$5.evaluate(DefaultResultSetHandlerFactory.java:156)
at org.sql2o.tools.AbstractCache.get(AbstractCache.java:49)
at org.sql2o.DefaultResultSetHandlerFactory.newResultSetHandler(DefaultResultSetHandlerFactory.java:173)
at org.sql2o.PojoResultSetIterator.<init>(PojoResultSetIterator.java:20)
at org.sql2o.Query$14.iterator(Query.java:547)
at org.sql2o.Query.executeAndFetch(Query.java:588)
at org.sql2o.Query.executeAndFetch(Query.java:574)
at lol.discordbot.database.QueryServerInfo.getCurrent(QueryServerInfo.java:31)
at lol.discordbot.command.Query.execute(Query.java:20)
at lol.discordbot.command.CommandsListener.onMessageReceived(CommandsListener.java:39)
I think you misunderstand what column mappings are. Column mappings are used to map column names to object-field names.
You should first create a data class to hold the result of your query. From your code above, I assume that you are trying to fetch players.
public class Player {
public String date;
public String playerList;
public String playerCount;
public String playerMax
}
(Consider to use better data types. Date for dates, int for counts, etc)
Then you can use sql2o to fetch data
List<Player> players = con.createQuery(sql).executeAndFetch(Player.class);
There is a much better way now.
.setAutoDeriveColumnNames(true)
Example
try (Connection con = sql2o.open()) {
List<Player> l = con.createQuery(sql)
.setAutoDeriveColumnNames(true)
.executeAndFetch(Player.class);
}
https://groups.google.com/g/sql2o/c/3H4XJIv-i04

Java ResultSet.getTimestamp() attaches millisecond to output

I have a table timestamptest with a single column timestamp of type timestamp without time zone.
I inserted a value to this table :
insert into timestamptest values('2015-09-08 13:11:11')
The timestamp does not contain any millisecond value.
On selecting this data in pgAdmin, it is displayed same as above.
But when I fetch this data using jdbc connection, the value displayed is with milliseconds.
Class.forName("org.postgresql.Driver");
Connection lConnection = null;
lConnection = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/postgres","postgres", "Password#123");
String lQuery = "select * from timestamptest";
Statement lStatement = lConnection.createStatement();
ResultSet lResultSet = lStatement.executeQuery(lQuery);
while(lResultSet.next()) {
System.out.println(lResultSet.getTimestamp(1));
}
Output : 2015-09-08 13:11:11.0
The desired output is 2015-09-08 13:11:11
It can be achieved by using SimpleDateFormat :
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(lResultSet.getTimestamp(1).getTime())
Can it be possible without using SimpleDateFormat? Is there any other way by which the result set itself gives me in the desired format?
What I need is that the statement
lResultSet.getTimestamp(1)
directly gives me the output 2015-09-08 13:11:11.
Its not possible. Since ResultSet.getTimestamp(1) return class that extends java.sql.TimeStamp. Returning class based on Database driver. And also we cant change the toString implementation of that.
Yes you can - but you're not going to like it.
class MyTimestamp extends Timestamp {
public MyTimestamp(long time) {
super(time);
}
public MyTimestamp(Timestamp ts) {
this(ts.getTime());
}
#Override
public String toString() {
String s = super.toString();
return s.substring(0, s.lastIndexOf("."));
}
}
public void test() {
System.out.println("Hello");
Timestamp t = new Timestamp(System.currentTimeMillis());
System.out.println(t);
System.out.println(new MyTimestamp(t));
}

Java Setting Array values then loop through and set object field equal to array values

I have a pretty introductory question that I hope can get answered rather easily.
Currently I am trying to write something that queries my DB, returns result set (list of account id's) and then sets those account id's into an array so that I can populate an object with the values.
My object is going to be used as input into another method I have written but I can't figure out how I go about populating my account_id field on it with the values in my array that I returned in the result set. There doesn't seem to be any "setter" methods for lack of a better term on my array of type String.
I was able to get the array to populate with acct_id's from the result set and print them out so I know that I do have information coming back.
Below is the snippet I currently have, any help/improvements I could make would be greatly appreciated!
try {
connection = DriverManager.getConnection(url, user, password);
st = connection.createStatement();
rs = st.executeQuery(sql);
List<Long> array = new ArrayList<Long>();
while (rs.next()) {
array.add((long) rs.getLong("acct_id"));
for (Integer i = 0; i < array.size(); i++) {
System.out.println(array.get(i));
GetSummaryRequest request = new GetSummaryRequest();
request.accountKey = new AccountDTO(array[i]);
}
}
} catch (SQLException e) {
System.out.println("Connection failed.");
e.printStackTrace();
return;
}
if (rs.next()) {
System.out.println(rs.getString(1));
} else
System.out.print("Failed. Try again");
}
If my understanding is correct you may need the code below which is used to store all the account id's inside an array and you can use this to pass as a parameter to another method.
ArrayList<GetSummaryRequest> array1=new ArrayList<GetSummaryRequest>();
GetSummaryRequest request = new GetSummaryRequest();
while (rs.next())
{
request=new GetSummaryRequest();
request.accountKey=rs.getString("acct_id");
array1.add(request);
}
Now you have ArrayList of GetSummaryRequest with accountKey for each object.
if i understand correctly accountkey is integer right?
you can use Integer.parseint('your string!') class to convert the string to int.
i hope it helps
First of all , storing newline separated values in one column is not a good practice. This is against atomicity principle and will lead you to problems soon - ex., total number of accounts? how do you find it?
Once you convince yourself with this, you can use only one loop like this
List<GetSummaryRequest> summaryRequests = new ArrayList<GetSummaryRequest>();
while (rs.next()) {
String em = rs.getString("acct_id");
GetSummaryRequest request = new GetSummaryRequest();
request.accountKey = em;
summaryRequests.add(request);
}
return summaryRequests;
Probably you need something like that:
// First you get all ids
List<String> accountsIds = new ArrayList<String>();
while (rs.next()) {
accountsIds.add(rs.getString("acct_id"));
}
// Then iterate ids
for (String id : accountsIds) {
GetSummaryRequest request = new GetSummaryRequest();
request.accountKey = id;
}

Write Java Vector To Delimited File

I am connecting to an Oracle database and querying multiple tables. My current code creates the connection and calls a PL/SQL function which contains the query. Once I have the result set, I add it to a Vector (as I am unsure the number of records each query will result in).
My problem is that I am unsure how to write a delimited file from the Vector. I imagine once I have added my result set to it, it is simply one gigantic string. I need to be able to receive each field from the query and delimit between them, as well as keep rows separate.
Here is my code:
public static void main(String[] args) throws SQLException {
// instantiate db connection
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}catch (Exception e) {
throw new SQLException("Oracle JDBC is not available", e);
}
// define connection string and parameters
String url = "jdbc:oracle:thin:#//host:port/sid";
Connection conn = DriverManager.getConnection(url, "USERNAME","PASSWORD");
CallableStatement stmt = conn.prepareCall("{? = CALL <functionname>(?)}");
// get result set and add to a Vector
ResultSet rs = stmt.executeQuery();
Vector<String> results = new Vector();
while ( rs.next() ){
results.add(rs.getString(1));
}
// close result set, sql statement, and connection
rs.close();
stmt.close();
conn.close();
// write Vector to output file,
// where the file name format is MMddyyyy.txt
try {
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMddyyyy");
String dateStr = sdf.format(cal.getTime());
FileWriter fwrite = new FileWriter(dateStr + ".txt");
BufferedWriter out = new BufferedWriter(fwrite);
for(int i = 0; i < results.size(); i++)
{
String temp = results.elementAt(i);
out.write(temp);
}
out.close();
}catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
I am just unsure how to go about getting the information from the db and writing it to a delimited file. Thanks in advance!
If you are unsure about the number of fields in each of your rows, then probably, it won't be possible. Because to fetch all the field values from database, you need to know what is the type of each fields, and the number of fields.
But, I'll post an example for when you have fixed number of fields, that you know.
Suppose you have 4 columns per row. Now to display it in tabular form, you would have to use List of List.
If you are using Vector, use Vector of List.
Here's an example for List of List: -
List<List<String>> results = new ArrayList<List<String>>();
while ( rs.next() ) {
List<String> tempList = new ArrayList<String>();
tempList.add(rs.getString(1));
tempList.add(rs.getString(2));
tempList.add(rs.getString(3));
tempList.add(rs.getString(4));
results.add(tempList);
}
Then to print it, use this loop: -
for (List<String> innerList: results) {
for (String fields: innerList) {
System.out.print(fields + "\t");
}
System.out.println();
}
You can write it in the same form to your BufferedWriter.
Use results.toString() and truncate the braces([]) from resulting string to write all values as comma separated at once in the file.
//toString() returns comma separated string values enclosed in []
String resultString = results.toString();
//truncate leading '[' and termincating ']'
resultString = resultString.substring(1, resultString.length()-1);
//if comma is not your delimiter then use String.replaceAll()
//to replace `,` with your delimiter
//write comma separated elements all at once
out.write(resultString);
So here if you have added str1, str2 in the results Vector, then resultString with have value as str1, str2, which you may write at once using your BufferedWriter out.
Also please use Generics in both the sides of initialization as:
Vector<String> results = new Vector<String>();

how to add a check in Java code for fetching only non-negative values from result-set

In my Java code I have embedded a SQL query which fetches data from a database and stores it in a result-set. I want to add a function or a piece of code which will take only non-negative data from the result-set for further processing.
Assumption: The result set can contain positive/negative/zero data values as well as characters. Also i cannot change the SQL query as its out of my scope.
try something like this, i think it will do the job
private ArrayList getNegativeNumbers(ResultSet rs, String coulumnName ) throws SQLException
{
ArrayList ret = new ArrayList();
while(rs.next()){
try {
int x = rs.getInt(coulumnName);
if(x>=0){
ret.add(new Integer(x));
}
} catch (Exception ex) {
String x = rs.getString(coulumnName);
ret.add(x);
}
}
return ret;
}
UPDATED 2. Sorry for my edits, i missread the question
while (resultSet.next()) {
if(resultSet.getInt("Column name") > 0);
Processmethod(resultSet.getInt("Column name") );
}

Categories