I have a class called "Database" that is working perfectly well. It queries a database and returns the results as a string. When I call the class from my "Test" class it returns the results string and I can print it with System.out.println().
I'm trying to use this class on a JSP page using the same two lines of code to instantiate the class and get the string output. When I try to output on the JSP page I get nothing. What am I doing wrong? I'm completely stumped.
Class Code:
public class Database {
static String[][] reservations = new String[7][20];
public Database (String theDate) {
String url = "jdbc:mysql://myurl.com:3306/";
String driver = "com.mysql.cj.jdbc.Driver";
String user = "myusername";
String pass = "mypassword";
String db = "class";
String options = "?useSSL=false";
try (Connection conn = DriverManager.getConnection(url + db + options, user, pass);
Statement statement = conn.createStatement()) {
String query = "select reservation.first, reservation.last, startday, numberofdays, guides.first as guidefirst, guides.last as guidelast, locations.location from reservation left join guides on reservation.guide = idguides left join locations on reservation.location = idlocations where StartDay >= " + theDate;
ResultSet rs = statement.executeQuery(query);
int row = 0;
while (rs.next()) {
reservations[0][row] = rs.getString("first");
reservations[1][row] = rs.getString("last");
row++;
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public String getStringRes () {
String returnString = "";
for(int i=0; i<20; i++) {
if (reservations[0][i] != null) {
returnString += i + " " + reservations[0][i];
returnString += " " + reservations[1][i] + "\n";
}
}
return returnString;
} }
JSP Code:
<%# page import="mypackage.Database" %>
<%
Database db = new Database("2015-07-01");
String str = db.getStringRes();
%>
<%= str %>
Your code contains 3 mistakes.
The most problematic
} catch (SQLException e) {
e.printStackTrace();
}
Don't ever do that. Go into your IDE settings and eliminate this template. It should be throw new RuntimeException("Unhandled", e); instead.
Here's what happened: Your SQL statement is erroneous (in two ways, even). This causes an exception. Your code handles this by ignoring it (it's printed, but, your code finishes normally). Hence, the string result remains blank (because it starts out that way and the code that is supposed to give it its real value never ran, due to the exception that you ignored).
Your SQL is broken.
The actual explanation is that date literals need to be in quotes, in SQL. Yours is not.
But that's not how you pass parameters into SQL.
The bigger issue is that passing any value like this into an SQL means your machine will be hacked in a matter of days. That's called 'SQL injection'. You don't want it. The solution is preparedstatements, where you let the JDBC driver and/or the database take care of escaping or otherwise passing string data without the SQL db engine trying to interpret it as SQL (Because, obviously, letting arbitrary users type stuff in that your DB engine then treats as SQL means you're just waiting for someone to construct some SQL such that your db engine ends up executing DROP TABLE reservation CASCADE; EXECUTE 'FORMAT C: /Y'; --.
Minor style nit
Doing business logic in constructors is a bad idea. The query should be done from getStringRes, most likely. That's also a bit of a crazy method name. Not very informative.
Which gets us to...
try (Connection conn = DriverManager.getConnection(url + db + options, user, pass);
PreparedStatement statement = conn.prepareStatement("SELECT reservation.first, .... FROM .... WHERE StartDay >= ?")) {
statement.setString(1, theDate);
try (ResultSet rs = statement.executeQuery()) {
...
}
} catch (SQLException e) {
throw new RuntimeException("unhandled", e);
}
Related
Submitting a query from SQLiteStudio returns the expected result from a View.
However, when the same query is sent from my program in java, the result is different for some queries.
ie: SELECT Rev FROM PartRevs WHERE PartNumber = '800111'
This returns the expected result of "B" when executed within SQLiteStudio. However, then the same query is executed from JAVA, it returns "A". Only one result is returned with both queries.
This does not happen consistently. Most queries work, but it occasionally does not work.
The 'Rev' or Revision of a given part is pulled from another table called 'ECO_TDA_Linewise'. Each time a new revision is released for a given part, a new line is added with increasing index numbers.
I believe the problem comes from the way the 'PartRevs' view works. Of the many other tables and queries, this is the only one that has an issue.
Here are the code blocks that interact with the database:
public String GetRevision(String PartNumber) {
String sqlStatement = "SELECT Rev FROM PartRevs WHERE PartNumber = '" + PartNumber + "'";
return getDatabaseResult(sqlStatement, "Rev");
}
public String getDatabaseResult(String sqlStatement, String Column) {
String result = "";
try (Connection conn = FulfillmentWorkorders.connect();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sqlStatement)) {
result = rs.getString(Column);
conn.close();
} catch (SQLException e) {
System.out.println("\"" + sqlStatement + "\" throws exception: " + e.getMessage());
}
return result;
}
I want compare to the data sent with all data in the db. this coce compare the date insert only with the last row. how can I compare with all row in the db?
................................................................................................
String sData= request.getParameter("idatadata");
String sAzienda= request.getParameter("idazienda");
String sCommessa= request.getParameter("idcommessa");
String date = "";
String company = "";
String order = "";
Connect con = new Connect();
try {
Connection connection = con.createConnection();
Statement statement = connection.createStatement();
String sql ="SELECT * FROM table";
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()) {
date = resultSet.getString("iddata");
company = resultSet.getString("idazienda");
order = resultSet.getString("idcommessa");
}
if((sData.equals(date) && sAzienda.equals(company)) && sCommessa.equals(order)) {
out.print("already sent");
con.closeConnection(connection);
}
else {
DbConnect.insertInDb(connection, sData, sOre, sMinuti, sAzienda, sCommessa, sRifInterno);
dbc.closeConnection(connection);
response.getWriter().append("ok! ");
}
} catch (Exception e) {
e.printStackTrace();
}
}
The reason why you are checking only the last row, is that your while loop keeps overwriting your local variables each time you retrieve a row:
while(resultSet.next()) {
// these lines overwrite the local vars for each row
date = resultSet.getString("iddata");
company = resultSet.getString("idazienda");
order = resultSet.getString("idcommessa");
}
But you don't actually check the local vars inside the loop before moving on to the next row from the db. You should add the check into the loop:
while(resultSet.next()) {
date = resultSet.getString("iddata");
company = resultSet.getString("idazienda");
order = resultSet.getString("idcommessa");
// add your check here
if((sData.equals(date) && sAzienda.equals(company)) && sCommessa.equals(order)) {
out.print("already sent");
break;
}
}
Preferably, just perform a select based on the data you are looking for. If you get no results, then the data isn't in the db. This method is much more efficient. If you do decide to go down this path (which is a good idea), use a prepared statement so that you don't introduce a SQL injection vulnerability into your code.
I have a problem with a really slow connection between my Java code and a MySQL remote Database when i use multiple query.
This is my code
ArrayList<Server_Log> ar =Server_Log_Utilities.getBy2Dates(cmb_date.getSelectedItem() + "", cmb_date2.getSelectedItem() + "");
for (int c = 0; c < ar.size(); c++) {
Server_Log sl = ar.get(c);
String username = User_Utilities.getUserName(sl.getUser() + "");
String row[] = {sl.getDate(), sl.getTime(), username, sl.getReff(), sl.getDescription()};
}
but I user this code data will load fast
ArrayList<Server_Log> ar =Server_Log_Utilities.getBy2Dates(cmb_date.getSelectedItem() + "", cmb_date2.getSelectedItem() + "");
for (int c = 0; c < ar.size(); c++) {
Server_Log sl = ar.get(c);
String row[] = {sl.getDate(), sl.getTime(), sl.getReff(), sl.getDescription()};
}
this is User_Utilities.getUserName(sl.getUser() + ""); Method
public static String getUserName(String id) {
String UserName="";
try {
Connection con = new DBCon().getConnection();
ResultSet rst = DBHandle.getData(con, "SELECT username FROM user WHERE id='" + id + "'");
while (rst.next()) {
UserName =rst.getString(1);
}
con.close();
} catch (Exception ex) {
Logger.getLogger(User_Utilities.class.getName()).log(Level.SEVERE, null, ex);
}
return UserName;
}
Server_Log_Utilities.getBy2Dates(cmb_date.getSelectedItem() + "",
cmb_date2.getSelectedItem() + ""); Method
public static ArrayList getBy2Dates(String date1, String date2) {
try {
ar = new ArrayList<>();
Connection con = new DBCon().getConnection();
ResultSet rst = DBHandle.getData(con, "SELECT * FROM server_log WHERE date BETWEEN '" + date1 + "' AND '" + date2 + "' ORDER BY `date`");
while (rst.next()) {
Server_Log ci = new Server_Log();
ci.setId(rst.getInt(1));
ci.setDate(rst.getString(2));
ci.setTime(rst.getString(3));
ci.setReff(rst.getString(4));
ci.setDescription(rst.getString(5));
ci.setUser(rst.getInt(6));
ar.add(ci);
}
con.close();
} catch (Exception ex) {
Logger.getLogger(Student_Utilities.class.getName()).log(Level.SEVERE, null, ex);
}
return ar;
}
When accessing a remote database, especially over a slow link, the number of SQL statements executed is very important.
This is why the JDBC API support concepts like statement batching.
In your case, you're calling getUserName for every record in ar. Consider ways to reduce the number of calls.
Example 1: If user is usually the same, or only a few users are generating log entries, caching the user names would eliminate redundant lookup.
Example 2: Rather than looking up the user in the client, modify the Server_Log_Utilities.getBy2Dates to add a JOIN to the User table. This way, no extra turn-arounds to database will be needed.
Example 3: Instead of calling getUserName individually in a loop, collect the user ids, and lookup the names in a batch. Use either a JDBC batch of multiple SELECT statements, or use a single statement with UserId IN (?,?,?,?,...).
Basically, I have to show a list with the data from a database table [that part is working] and afterwards I have to show the highest Date [a date variable in the table]. The second part is not working no matter what I do.
Here's the code
try {
String SQL = "SELECT * FROM tb_rafael";
ResultSet rs = BD.consultar(SQL);
String tab = "";
int numReg = 0;
while (rs.next()) {
tab+="<TR>";
tab+="<TD>" + rs.getString("nme_rafael") + "</TD>";
tab+="<TD>" + rs.getString("dta_rafael") + "</TD>";
tab+="</TR>";
numReg++;
//mDat = rs2.getString("dta_rafael");
}
rs.close();
dados.put("DADOS", tab);
dados.put("NUM_REG", String.valueOf(numReg));
//Pegar Data Maior
String SQL2 = "SELECT MAX(dta_rafael) FROM tb_rafael";
ResultSet rs2 = BD.consultar(SQL2);
String mDat = "";
//while(rs2.next()){
mDat = rs2.getString("dta_rafael");
//}
rs2.close();
dados.put("MDA", mDat);
} catch (Exception ex) {
dados.put("MSG", "Erro: " + ex.getMessage());
}
What you want to look at is past the commentary line "Pegar Data Maior". That's the part that is not working. I've tried adding a while, using a different ResultSet, using the same ResultSet and none of those worked. I know it's not an issue with the SQL query since I tested it with the workbench and it returned me the data I want.
To be more specific, I don't get an error message or anything, the dados.put simply does not work and I get just this:
How the HTML code looks:
The data should show up where the {MDA} is. Anyone have any ideas?
The query SELECT MAX(dta_rafael) FROM tb_rafael may not return a column name, which you later try to retrieve, rs2.getString("dta_rafael");
I'd change the query to SELECT MAX(dta_rafael) AS Max_date..., and reference to MAX_date thereafter.
Hi my aim is to load combobox with vaules from a database the code below works fine with one issue i get two of the first item so what must i do to prevent this
public void loadCombos() {
try {
try {
String cs = "jdbc:mysql://localhost:3307/booksalvation6";
String user = "root";
String password = "letmein";
jComboBox2.removeAllItems();// make sure old data gone
PreparedStatement pstpost;
ResultSet rspost;
conCombos = DriverManager.getConnection(cs, user, password);
for (int i = 1; i < 11; i++) {
String querypost = "select * from post "
+ "WHERE postage_id =" + i;
// load postage selections
pstpost = conCombos.prepareStatement(querypost);
rspost = pstpost.executeQuery();
while (rspost.next()) {
String Mypost = rspost.getString(6);
jComboBox2.addItem(Mypost);
}
}
} catch (SQLException ex) {
Logger.getLogger(BasicFrame.class.getName()).log(Level.SEVERE, null, ex);
}
conCombos.close();
} catch (SQLException ex) {
Logger.getLogger(BasicFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
You are using PreparedStatement but not in proper way.
Since you are looking only for one column to fetch all the column values which have postage_id between 1 to 10.
You can achieve it in single query:
select unique(combo_value_column_name) from post
where postage_id>=? and postage_id<=?
set the parameter via calling PreparedStatement#setInt(index,value) set it 1 and 10.
Just fetch single column and only unique values.
It's better explained under Java Tutorial on Using Prepared Statements
Instead of calling JComboBox#addItem() first prepare the whole list then finally set it once.
Read more...
Final Note: Follow Java Naming Convention.