In my email management system, I am retrieving data from MySQL database into Java netbeans. But it is only showing the data for one person. It should move on to next row on each rs.next(), but it is not seemingly. Following code is written in the "Next" Button, which moves on to the next selection in a JList.
try {
DefaultListModel model = new DefaultListModel();
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/email management system","root", "ok" );
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select * from inbox,curlogin where inbox.rmail like curlogin.mail;");
String fname="";
list.setSelectedIndex((list.getSelectedIndex()+1));
rs.next();
fname = rs.getString("name");
String sender = rs.getString("First");
String reciever = rs.getString("recipent");
String sub = rs.getString("subject");
String msg = rs.getString("message");
String mail = rs.getString("Email");
Date d = rs.getDate("Date");
Timestamp ls = rs.getTimestamp("Seen");
Time t = rs.getTime("Time");
subject.setText(sub);
message.setText(msg);
date.setText(""+d);
time.setText(""+t);
lseen.setText(""+ls);
email.setText(mail);
// TODO add your handling code here:
} catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(inbox.class.getName()).log(Level.SEVERE, null, ex);
}
user2642282's answer is technically correct but it is lacking explanation and user2642282 misunderstood what your attempting to do. Your half way to the solution with your code but it requires some changes. Lets start with this:
rs.next()
What your doing here is accessing the result set and normally you would write your code like this to loop through all the returned results:
ResultSet rs = stmt.executeQuery("your SQL statement here");
while (rs.next()) {
fname = rs.getString("name");
//...all your original code here
email.setText(mail);
}
Notice how the code is basically exactly the same as your original code except we added the while loop. Normally this would allow you to write out, display, or store each record (email in this case) returned by the query however you want/ need to do something different. So I'll explain what options I think you have next but first here is a link to the Java Docs that will teach everything you need to know about the above code.
Option 1 - Traditional Way
The way most email desktop app's handle this is simply to load all the emails and store them on the file system. This would mean that you need to change your code to load all emails at certain times. Maybe at startup and then every 60 seconds after that check for new messages (usually you should limit checking to no lower than 5 minutes). Then when a user opens a message you load it from its file. When they press next or previous you simply load in the next or previous email from the file system. So your email app is more of a file reader that parses email files and loads their content into your window. You will need to devise a filing system as well. For example naming and saving the emails as their timestamp making it easy to find the next and previous emails. You will also have to deal with deleted emails.
Option 2 - Easy but Bad Practice
Without having to change your code to much you could track which row from the database you read last and run the SQL query every time the user presses the next or previous buttons. You would use the same code your originally posted but add the following:
Check for when next() returns false meaning there is no next or previous email
Add in a variable that keeps track of the last row you read from in the database
Change your SQL query to only return the next or previous row
Option 3 - Hybrid
You could attempt to change your code to the one I showed you and do a hybrid of option 2. What you would do is track the next and previous 10 rows from the database for example. So lets say you last read from row 50. You would run the code I gave you and save all the emails from row 40 to row 60. You have two options for saving the emails:
File system which creates a bit more work but saves memory.
As objects that could take a lot of memory but is easy and fast.
EDIT - Answer to question from comments
Here is how I imagine your code working using option 2 or 3. Notice that ... means I left out code you already have but would just get in the way of this example:
int lastRowRead = 0; // starts as 0 when the program starts
//...all your original code here
ResultSet rs = stmt.executeQuery("...LIMIT "+ lastRowRead +",20;");
if(rs.next()!=false) {
fname = rs.getString("name");
//...all your original code here
email.setText(mail);
}
This code is for option 3. The int lastRowRead should be a global variable that you can keep track of and change each time you run a query to get more messages. You will need to figure out how to catch errors, for example trying to query a row number that doesn't exist. I won't help you code this because it is a good learning opportunity. NOTE: In case you are not familiar with SQL LIMIT here is another example:
....LIMIT 40, 20;
What this means is go to row 40 in the table and read the next 20 rows. So it will return emails from 40 to 60. So if you want to go the super easy but not at all efficient route your SQL query could have:
...LIMIT 40, 1;
This will only return the row number requested. So all you have to do is track which row you last read from and add or subtract 1 from it and run the query again to get the next or previous email.
You are missing a loop that iterates over the resultset. The call
rs.next()
gives you the first row of your SQL result. Try to loop over the results using until rs.next() returns false
two points:
one: if JList current selected value has not changed, when you click next button , you should change your sql , then you can see one's email one by one. at the end of your sql, you should add
select * from inbox,curlogin where inbox.rmail like curlogin.mail limit #{offset} 1
to fix your sql . the offset is a veriable from 0,1,2,3.... it represents one's email from 1 to N
two: you haven't show some event code about JList after selected value was changed. if it was changed , your should get the selected item, and pass it to your sql to filter person's email. so your sql should accept person's name .
Related
I'm migrating a Java application to VB.Net and I try to translate following Java code
Statement stmt
= conx.createStatement
(ResultSet.TYPE_SCROLL_INSENSITIVE
,ResultSet.CONCUR_READ_ONLY
);
ResultSet rsSheet = stmt.executeQuery(sSql);
bStatus = rsSheet.next();
...
bStatus = rsSheet.first();
In this code, a scrollable ResultSet is used. I can read the records returned by executeQuery() function and when I have terminated to read them, I can read it again without interrogating the Database a second time.
You can find some information on ResultSet here https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
My translated code is following
Dim cmd = conx.CreateCommand()
cmd.CommandText = sSql
Dim rsSheet as OracleDataReader = cmd.ExecuteReader()
bStatus = rsSheet.Read()
...
bStatus = rsSheet.? 'how to read first record again ?
But I don't find how to do so that OracleDataReader is scrollable ?
I can read the ResultSet from first to last record but I cannot read it again.
The only simple solution that I found to read all these records again is to call ExecuteReader() function a second time.
QUESTIONS
Is OracleDataReader Class scrollable ? How ?
Does another Class exist to do the job ? Which ?
PS: using Linq is not solution because SQL statements are executed in an environnement where Database structure is unknown. It is impossible to create entities.
A DataReader is one way only. Use a DataTable. This is an in memory representation of the result set. You can also use a DataTable to as a DataSource for various controls. You can use Linq on a DataTable.AsEnumerable()
Private Sub OPCode()
Dim sSql = "Your command text"
Dim dt As New DataTable
Using cn As New OracleConnection(ConStr),
cmd As New OracleCommand(sSql, cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
'Code to read data.
End Sub
EDIT
The simplest way to see what is in the DataTable is to display it in a DataGridView if this is WinForms.
DataGridView1.DataSource = dt.
To access a specific row and column.
Dim s = dt.Rows(1)("ColName").ToString
The Rows collection starts with index 0 and the column name is from you Select statement. You then need to convert to the datatype with .ToString or Cint(), CDbl() etc. as this returns an object.
My Logcat shows me (correctly) all messages that I want returned, but when I ask the code to display the same thing on another php page, it goes completely wack.
Note that is this code, $from = "r", and $to = "".
Here is my code:
<?php
session_start();
/* connect to database */
$db = mysql_connect("localhost", "root", "root");
if (!$db)
die('could not connect');
mysql_select_db('androidp2p')
or die("could not select database");
/* variables */
$from = mysql_real_escape_string($_POST['from']);
$to = mysql_real_escape_string($_POST['to']);
$message = mysql_real_escape_string($_POST['message']);
/* conditional code */
if (isset ($POST['to']))
{
/* user wants to send a message */
$query = "INSERT INTO messages (fromuser, touser, message) VALUES ('$from', '$to', '$message')";
mysql_query($query)
or die("\n\ndatabase error!\n". mysql_error());
echo "ok. Messages have been saved.";
}
else //if (!isset ($POST['to']))
{
/* user wants to retrieve his messages */
$query = "SELECT * FROM messages WHERE touser='$from'";
/* echo test 1 */
echo $query;
$result = mysql_query($query)
or die("\n\ndatabase error!\n". mysql_error());
$mailbox = array();
while($row = mysql_fetch_assoc($result))
{
$mailbox[] = $row;
}
/* echo test 2 */
echo "{ \"mailbox\":".json_encode($mailbox)." }";
$name = "{ \"mailbox\":".json_encode($mailbox)." }";
$_SESSION['myValue']=$name;
}
?>
On page 2 (test.php):
<?php
session_start();
echo $_SESSION['myValue'];
?>
Here are the entries in the db:
This is my logCat:
I/RESPONSE(4591): SELECT * FROM messages WHERE touser='r'
I/RESPONSE(4591): { "mailbox":[{"id":"117","fromuser":"qw","touser":"r","message":"zx","timestamp":"2013-04-13 01:30:59"}] }
Now above I want you to see that touser is r. This entry (in the db) is what I wanted to return, i.e. all entries where the field "touser" contains the value "r".
Now, this is my test.php page:
{ "mailbox":[{"id":"132","fromuser":"r","touser":"","message":"","timestamp":"2013-04-13 15:45:03"},{"id":"123","fromuser":"r","touser":"","message":"","timestamp":"2013-04-13 13:41:23"},{"id":"122","fromuser":"r","touser":"","message":"","timestamp":"2013-04-13 13:30:53"},{"id":"133","fromuser":"","touser":"","message":"","timestamp":"2013-04-13 15:45:21"}] }
EDITED:
As you would see, it returned all touser entries that were blank (or null). My interpretation of this behaviour is that while the code is running, the $from variable is in fact 'r' (and that's why it's saved in logcat correctly), but after the code executes there is presently no value in $from so it just outputs the result for $from = null.
Should php be doing this? I thought that whatever code was executed and echoed at the time would have been output on the page and STAYED there until I re-ran the code. Any suggestions on how to fix this?
EDITED
The point of all this is to use the JSONParser code I got from here, to get particular rows from a database, and put them into the android's database into particular fields. I've tried modifying my JSONParser code to use BackgroundTask like this, and you can take a look at this.
This is what the project is trying to achieve: The first user can post a message to a server db whch contains 'from' (which would be user1's cell number), 'to' (which would be destination or user2's number), and a message (which is his location). The second user uses a polling service to periodically retrieve his messages from the database, i.e. all entries in the database where his number would be in the "to" field and store those entries into a database on his phone (and automatically delete those entries from the server's db). Everything is basically working, I think, except the part where I get particular entries from the server's db.
I decided to use JSONParsing because it can take an array of db entries and make a string out of each entry, making it easier to store in my android's db. But this is where it lacks..finding a way to retrieve particular entries of a db..I have not figured out a way to do this. Any help to point me into the right direction?
Sessions are designed to be unique for each visitor, this is done by remembering the session in a cookie. Your computer will have a different session to your Android. And in fact each browser on your computer will have a different session, unless they have a way of sharing cookies.
Furthermore, scripted requests (like Android code) do not automatically remember cookies and send between requests, and so they may start a new session for each request, and lose information from the previous session.
There are a number of solutions...
Restructure your process so that you do not need to retain the messages in this way - just returning the messages from the script that deletes them maybe? Or having the first script return messages and pass the second script the message IDs to delete. This last point might also be "safer" as you're not deleting anything until you know the app has received it.
Find a way to remember cookies and send them with subsequent requests. How do I make an http request using cookies on Android? might be useful for this.
Get the session ID from PHP and send it along with all your requests. You can get and set the session ID in PHP with session_id().
The last two are not great practice for APIs, as we aim for APIs to be stateless, but they may work for you.
Yeah i see the issue, thats odd i have not come across this before, but it appears you can add something to your SQL statement to correct it...
SELECT * FROM messages WHERE touser='$from' AND WHERE touser IS NOT NULL
I think that will prevent the null rows from showing. The IS NOT NULL should be the key.
I'm developing an application in which I pick rcode(numbers) from the database with the name. If the name is present it will display the rcode associated with it. The output like
10001
Suppose, if two names are present with the same name, it will display like
10001 10002
Here is my servlet code for this..
ResultSet rs=stmt.executeQuery("select * from newfarmer where rname='"+get+"'");
while(rs.next()){
username=rs.getString("rname");
if(get.equals(username)){
rcode=rs.getString("rcode");
out.println(rcode);
}
}
and,
I'm using the following code in my android application to get the data from it. That is I need to pick all the data something like where rname=" ". Now the problem is if two records with the same name are present, It will pickup only one record. But servlet outputs show as
10001 10002
In my application I count the total number of records and display it. But it shows only one
String line = null;
while ((line = reader.readLine()) != null) {
StringTokenizer st=new StringTokenizer(line);
count=st.countTokens();
Toast.makeText(getBaseContext(), count+" names found",
Toast.LENGTH_SHORT).show();
r_code=st.nextToken();
ff=1;
}
So, I need to access both the records and also count the total no.of records. Can anyone help to do this
out.println(rcode) adds a CRLF (which is ignored when you look at the output with a browser). What happens if you replace it with a space character ?
out.print(rcode);
out.print(" ");
use list to display the records and add one counter....,for list refer http://www.vogella.com/articles/AndroidSQLite/article.html
i am not able to understand why you are writting that inside if statement. you need not to write that statement as username will always be equal to get. remove that statement and try to run it again.
My mysql-query in Java always stops (i.e. freezes and does not continue) at a certain position, which namely is 543,858; even though the table contains approx. 2,000,000 entries. I've checked this by logging the current result-fetching.
It is reproducible and happens every time at the very same position.
"SELECT abc from bcd WHERE DATEDIFF(CURDATE(), timestamp) <= '"+days+"'");
Addition: It definitely is a Java error, I've just tried out this statement in Navicat (50s running time).
The query seems to freeze after the log tells me that it's now adding the result of position 543,858.
try {
...
ResultSet res = new ResultSet();
PreparedStatement stmt = new PreparedStatement(); // prepare statmenet etc.
stmt.setFetchSize(Integer.MIN_VALUE);
res = stmt.executeQuery();
...
System.out.println(res.getStatement());
...
while (res.next())
treeSet.add(res.getString("userid"));
} catch (Exception e) {
e.printStackTrace();
}
Edit: We were able to figure out the problem. This method is fine and the returned result (500,000 instead of 2,000,000) is right as well (looked up in the wrong db to verify the amount); the problem was, that the next method-call that used the result of the one posted above takes literally forever, but had no logging-implemented. So I've been fooled by missing console-logs.
Thanks anyways!
I think you might be running out of memory after processing half a million records. Try assigning more memory using command line options -Xmx etc. See here for more info about command line options.
In mysql to use streaming ResultSets you have to specify more parameters, not only fetchSize.
Try:
stmt = conn.createStatement('select ...', java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
and see if that works.
It's documented in the ResultSet section.
Strange that it doesn't throw exception, but this is the only suspect I have. Maybe it starts garbage collection/flushes memory to disk and it takes so much time it doesn't get to throw it.
I would try to add to your query " LIMIT 543857" and then " LIMIT 543857" and see what happens.
If the above does not help, use the limit directive combined with order by.
I suspect that there is invalid entry in your table and the way to find it is binary search.
As a learning exercise I have adapted a series of Java servlets written by BalusC to store a list of images uploaded in a mysql database. The application works fine and displays a list of the images in the sequence they are read from the database statically in html. Howver, I am trying to adapt the html to display these dynamically in a slideshow. I have found several examples on the internet but all of them seem to hard-code the names of images in the browser code. I'm looking for some way of transfering the images read from the database query to a slideshow in the client.
The original source is here
After having researched several examples it seems that using javascript is the most common way for doing it, but I cannot find an example which does it dynamically here is my attempt (I am using javascript embedded with html within a java servlet) at it which fails to do more that print out the titles of the images in a consecutive list on the page (but no image):
try {
Class.forName(driver);
Connection con = DriverManager.getConnection(url+dbName, userName, password);
PreparedStatement ps = con.prepareStatement("select * from photos");
ResultSet rs = ps.executeQuery();
out.println("<h1>Photos</h1>");
while ( rs.next()) {
out.println("<h4>" + rs.getString("title") + "</h4>");
out.println("<script type=\"text/javascript\">");
out.println(" function clearScreen(){");
out.println(" document.image.src=displayphoto?id=\" + rs.getString(\"id\")\"");
out.println(" document.body.innerHTML=\"\";");
out.println(" setTimeout('clearScreen()','5000');}");
out.println("</script>");
}
con.close();
}
Any pointers or suggestions on a better way of doing this, even purely with Java servlets would be greatly appreciated.
Many thanks
Alastair
This code generates a <script> block defining the same clearScreen function for each photo found in the table (but with a different photo ID at each iteration).
It's not very clear what you're trying to do. To do a slideshow, you have to iterate over a list of picture IDs. You can store this list of IDs
as a JavaScript array in the HTML code. The servlet code would have to generate the JavaScript code defining an array of IDs
as an Iterator at server-side, in a session attribute. To display the next photo, the displayphoto servlet would have to get the iterator from the session, get its next ID, and serve the bytes of the image having this ID
nowhere. Each time a new photo must be displayed, its index would be passed to the displayphoto servlet, and the servlet would generate a SQL query to get the photo at this index. Of course, the SQL query would have to use some sort order to always return the photos in the same order.
If your goal is to implement the first solution, it's really not difficult. Here is how an array of three IDs (id1, id2 and id3) is declared in JavaScript:
var ids = ['id1', 'id2', 'id3'];
So, all you have to do is to generate the above String frm a List<String> containing "id1", "id2" and "id3". A simple loop will do:
StringBuilder jsArrayDeclaration = new StringBuilder();
jsArrayDeclaration.append("var ids = [");
boolean first = true;
for (String id : listOfIds) {
if (!first) {
jsArrayDeclaration.append(", ");
}
first = false;
jsArrayDeclaration.append("'");
jsArrayDeclaration.append(id);
jsArrayDeclaration.append("'");
}
jsArrayDeclaration.append("];");