rs = ldao.getLonaAllList(schemeName, memid, TStrCalcdt);
if(!rs.next())
{
MessageBox mb = new MessageBox(sh, SWT.ICON_INFORMATION);
mb.setMessage("No Data Found");
mb.open()
return;
}
while (rs.next()) {
//other code for bringing the dat
}
i want to check, if the record doesnot contain the data then it shows the message. but i found the problem that while getting the record in every case, the first recordset data is not displayed.
so please can any body help on this. how can i show that the record set does not contain any data without losing my first data in dataset
Since rs.next() already moves to the next record and you call it twice before you enter the loop body, it is clear that the first record gets skipped. Replace your while loop with a do-while:
do {
//other code for bringing the dat
} while (rs.next());
(All of this assumes you're actually talking about a ResultSet or something with a similar interface).
Related
This is a weird issue. I know I'm making a small mistake but not able to figure it out what exactly in it.
I'm executing one query and it has result set. First I'm validating if it doesn't has records then set one of the DTO attribute to false. If it has records, then iterate and do some business.
rs = partyPreparedStatement.executeQuery();
if(!rs.next()) { // It has records, but I'm checking with ! operator to make sure it goes to false or true.
purchaseDto.setPOIssued(false);
} else {
while (rs.next()) { // It has records, but still its not going to execute business
// Do some business here.
break;
}
}
Is the design correct?
If data is returned you will be ignoring the first row.
The first call to next() will already position the ResultSet to the first row (if there is data). But you don't do anything with that row, you immediately call next() again (in the while condition) thus ignoring the first row completely.
How you solve this problem is a matter of taste. I personally would simply count the number of rows processed:
If you only want to process the first row, you don't need a while to begin with:
rs = partyPreparedStatement.executeQuery();
if (rs.next()) {
purchaseDto.setPOIssued(true);
// process the data here
} else {
purchaseDto.setPOIssued(false);
}
You move the cursor two times so instead you can use do{}while loop :
if (!rs.next()) {
purchaseDto.setPOIssued(false);
} else {
do {
// Do some business here.
break;
} while (rs.next());
}
set the value default to false and in the loop to true
purchaseDto.setPOIssued(false);
while (rs.next()) { // It has records, but still its not going to execute business
// Do some business here.
purchaseDto.setPOIssued(true);
break;
}
For example:
public void removeStaleMovies(Set<String> updatedMovieList) {
Cursor cur = this.getReadableDatabase().rawQuery("SELECT id, title, year FROM movie", null);
cur.moveToFirst();
while (!cur.isAfterLast()) {
String title = cur.getString(1);
String year = cur.getString(2);
if (!updatedMovieList.contains(title + "-" + year)) {
// delete the row where 'id' = cur.getString(0)
// OR, delete the row using the object at the cursor's current position, if that's possible
// OR, if deletion isn't safe while iterating, build up a list of row id's and run a DELETE statement after iteration is finished
}
}
}
Is deletion safe to do? Or can it result in some unpredictable behavior? I am aware of this similar question, but I'm still unsure.
From a code safety standpoint, this should be OK, assuming that the result set of your query is less than 1MB. In that case, the Cursor holds in heap space the entire result set, so it is insulated from any changes to the underlying database.
That being said, you may want to build up a list of rows to delete, simply so you can delete them in a single statement, rather than a bunch of individual statements (though wrapping those individual statements in a transaction may give you similar performance characteristics).
I'm concerned about my Java client directly connecting to the MySQL server due to all of the issues that could occur, and the security risks I believe it could pose. Such as someone being able to decompile the file and get the login details for the database. As beautiful as it would be, I'm too scared to take that risk. I've written a PHP script to echo data that the client can interpret. The PHP script is what connects to the MySQL.
It's rather simple: Java->PHP->MySQL
I'm going to provide screenshots of the MySQL structure, so you may better understand when trying to visualize this.
id: possibly tid/sid
tid: teacher id, used to link to the teacher
sid: student id, used to link to the student
gid: grade id
aid: assignment id
gp: gained points
pp: possible points
Grading rows are for each assignment per student. So for example if a teacher had 30 students assigned to one assignment, there would be 30 rows in the grading tab and one in the assignments. Duplicate assignment names are NOT allowed.
When the client is requesting the data, I just use a buffered reader & URL to download the string. This is the example output of when the client receives the assignment names.
Test Assignment;Secondary Test Assignment;
This is what it looks like to the client once the column names are downloaded:
As you can see the first two columns are there by default, the last two are assignment names.
I want each row in the table to be a student. However, here is where my trouble comes in. I'm trying to receive the proper data from grading. I don't know how I'm going to do this. I have about 3 months experience with Java, so you could definitely call me a newbie.
Here is my idea, but I didn't think it was so great of an idea:
Search through all of the column names and insert the value into the proper column in that row where assignment name matches.
I didn't know how difficult that would be. I'm guessing the nice people who developed swing built something in for that, but I can't find any resources.
Does anyone have any recommendations on what to do in this situation? I feel lost.
Let's start with the Java client. Here is some code that reads from a php page and that creates a JTable out of it. (actually it's reading from a String for simplicity but you can easily change the code to match your real case, see the comment in the code).
public static void main(String[] args) throws Exception {
String receivedFromPHP = "Student ID;Student Name;Test Assignment;Secondary Test Assignment;\n"
+ "1;Luc;Test assignment 1;Secondary Test assignment 1;\n"
+ "2;Vador;Test assignment 2;Secondary Test assignment 2;";
BufferedReader br = new BufferedReader(new StringReader(receivedFromPHP));
// For real: br = new BufferedReader(new InputStreamReader(new URL("http://localhost/yourPhpPage.php").openStream()));
DefaultTableModel dtm = new DefaultTableModel();
String line;
boolean headersReceived = false;
while ((line = br.readLine()) != null) {
String[] columns = line.split(";");
if (!headersReceived) {
dtm.setColumnIdentifiers(columns);
headersReceived = true;
} else {
dtm.addRow(columns);
}
}
JTable table = new JTable(dtm);
JFrame f = new JFrame();
f.add(new JScrollPane(table));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Nothing really difficult until now. The real thing is to write the php page with the proper query. Obviously, you know better what you want your page to output but I guess your are going for something like this:
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "pinkfluf_dvonx");
/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
/* Select queries return a resultset */
if ($result = $mysqli->query("SELECT Name FROM City LIMIT 10")) {
printf("Select returned %d rows.\n", $result->num_rows);
/* free result set */
$result->close();
}
/* If we have to retrieve large amount of data we use MYSQLI_USE_RESULT */
if ($result = $mysqli->query('SELECT u.id AS "Student ID", u.username AS "Student Name", ... FROM members u, grading g, assignments a WHERE ...')) {
while($row = $result->fetch_array(MYSQLI_NUM)) {
for ($i=0; $i<sizeof($row); $i++) {
echo $row[$i] . ";";
}
echo "\n";
}
$result->close();
}
$mysqli->close();
?>
Of course, the code I give here is very approximative (given the information I could extract from your question) so it's certain that you'll need to adapt the code to make it work as you'd like to but I hope it can help you getting started (keep going :)).
As far as securing your database, I'd recommend creating a locked down user that can only execute stored procedures - then you don't have to worry about someone decompiling your code. They'd only be able to access what they can access through your code. Here's a tutorial on how to do that.
As far as your main question goes, I would recommend all your data gathering/sorting be done in your SQL query. If you're doing that in the JTable, you end up mixing your Model and View (see MVC for more detail).
So essentailly you want your data coming back from the query in this form:
Student; Student Name; Test Assignment; Secondary Test Assignment
Which means,
You need to add a relation between your grade table and your assignment table (most likely addding aid to the grading table)
You're going to need to come up with a slightly more complicated SQL Query - something like this:
Select g.sid, g.name, a.name from ASSIGNMENTS a
join GRADING g on a.aid = g.aid
where g.tid = 123123 order by g.name
Create a 2D array based on the data and put it in the table (If you're still using your PHP interface, you'll want to split the strings on your delimiters to create a 2D array.)
((DefaultTableModel)table.getModel).setDataVector(data, columnNames);
EDIT
If you're convinced you just want to search through the rows for a value, and then update a column in the row you found - this should get you in the right direction:
Integer searchStudentID = 123123;
int searchColumn = 0;
String updateValue = "Value";
int updateColumn = 3;
//Look through the table for the right row
Vector<Vector<Object>> data = ((DefaultTableModel)table.getModel()).getDataVector();
for(Vector<Object> row : data){
// If on the right row, update it
if(row.elementAt(searchColumn).equals(searchStudentID)){
row.setElementAt(updateValue, updateColumn);
}
}
This is the code I am working on:
if(connection.doDatabaseRead(findSQL))
{
ResultSet retRES = connection.getResultSet();
int i = 0;
// did we find anything
while( retRES.next() )
{
//read result from query
suiteNum.add(retRES.getString(i)); // this is the problem
i++;
//let other threads breathe
Thread.yield();
}
}
suiteNum is a string vector
When I try to add the database results to the vector the code crashes with this error.
java.sql.SQLException: Column Index out of range, 0 > 1.
I have the same piece of code working elsewhere in the program but I use real numbers like 0, 1 and 2 instead of i and it works fine.
As I do not know how many results the database request will have I need it to be dynamic but it will only work hard coded.
How can I make it work with i ?
The argument to getString is the column index, not the row index as you seem to think. The function returns the value of the given column in the current row, while next advances the cursor to the next row.
You probably mean:
suiteNum.add(retRES.getString(1));
in which case you can lose i altogether.
Java ResultSet objects are 1-indexed in this regard. The first element is at 1, not 0. See the javadoc.
EDIT: That's true too, but indeed the problem is this appears to be used as a row index! it's certainly the column.
This is your problem:
i = 0;
...
retRES.getString(i);
ResultSet.getString(i) gets a String from column number i
You want something like
while(retRes.next()) {
add(retRes.getString(1);
}
column index starts from 1
As I do not know how many results the database request will have I need it to be dynamic but it will only work hard coded. How can I make it work with i
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
See Also
ResultSetMetaData
Let your i start with 1 as specified in the API docs
if(connection.doDatabaseRead(findSQL))
{
ResultSet retRES = connection.getResultSet();
int i = 1;
// did we find anything
while( retRES.next() )
{
//read result from query
suiteNum.add(retRES.getString(i)); // this is the problem
i++;
//let other threads breathe
Thread.yield();
}
}
I am wondering how to check if the resultset has some records returned, just like below,
while(((ResultSet) rs).next()){
((ResultSet) rs).previous();
return true;
}
But I can't do this since the result set type is TYPE_FORWARD_ONLY, is there any handy API available for my case? wasNull is not the right one for certain, thank you for any pointers!
Even
if(!resultSet.isBeforeFirst()){
System.out.println("resultset contin no rows");
}
isBeforeFirst() returns true if the cursor is before the first row; false if the cursor is at any other position or the result set contains no rows
The answer is, you can't. That the nature of SQL row sets: You are notified when you hit the end, but you don't know until you try to get the next record and there isn't one. It's just the way it is.
Since you can not know before you make the rs.next() move about the state of your ResultSet you could probably:
run a count statement before your create your ResultSet or
do a first rs.next(), or rs.first() and use its contents in case your set is not empty like
this:
boolean state = rs.first(); // or rs.next();
if (state == false)
System.out.println("empty");
else {
System.out.println("not empty");
while (state) {
System.out.println(rs.getInt(1));
// use your row ...
state = rs.next();
}
}
If your first call to rs.next() is successful and it returned true, that means there are some records returned.