I'm new with java and sql query and for the user connexion, I connect to the DB and check if the login exists. Here is what I do :
requete = "SELECT Login,Password,DroitModifAnnuaire,DroitRecepteurDem,DroitResponsableDem,PiloteIso,Administrateur,DroitNews,DroitTenues,DroitEssai,Nom,Prenom FROM Annuaire WHERE Login='"
+ (request.getParameter("login") + "'");
instruction = connexion.createStatement();
jeuResultats = instruction.executeQuery(requete);
try{
jeuResultats.next();
} catch (SQLException e) {
e.printStackTrace();
}
if (jeuResultats.next() == false) {
loadJSP("/index.jsp", request, reponse);
}else {
loadJSP("/views/menu.jsp", request, reponse);
}
The login that I enter is good but it redirect me to index.jspand I have the error : the result set has no current row
I tried to search answer to this error but I didn't found. So why it returns me false ? While when I do System.out.println(jeuResultats.getString(1)); the login is printed.
jeuResultats.next(); moves your result to the next row. You start with 0th row, i.e. when you call .next() it reads the first row, then when you call it again, it tries to read the 2nd row, which does not exist.
Some additional hints, not directly related to the question:
Java Docs are a good place to start Java 8 ResultSet, for e.x., perhaps ResultSet.first() method may be more suited for your use.
Since you are working with resources, take a look at try-with-resources syntax. Official tutorials are a good starting point for that.
Also take a look at prepared statement vs Statement. Again, official guide is a good place to start
Make the below changes in you code. Currently the next() method is shifting result list to fetch the data at 1st index, whereas the data is at the 0th Index:
boolean result = false;
try{
result = jeuResultats.next();
} catch (SQLException e) {
e.printStackTrace();
}
if (!result) {
loadJSP("/index.jsp", request, reponse);
}else {
loadJSP("/views/menu.jsp", request, reponse);
}
Replace your code by below code:
requete = "SELECT Login, Password, DroitModifAnnuaire, DroitRecepteurDem, DroitResponsableDem, PiloteIso, Administrateur, DroitNews, DroitTenues, DroitEssai, Nom, Prenom FROM Annuaire WHERE Login = '"
+ (request.getParameter("login") + "'");
instruction = connexion.createStatement();
jeuResultats = instruction.executeQuery(requete);
try{
if (jeuResultats.next()) {
loadJSP("/index.jsp", request, reponse);
} else {
loadJSP("/views/menu.jsp", request, reponse);
}
} catch (SQLException e) {
e.printStackTrace();
}
Related
I had a situation where my code was getting hit by the deadlock issue with SQL Server for some transactions. So, I implemented a retry logic to overcome the same. Now, I'm facing a new problem. The problem is, whenever it retries, the batch which was tried to execute will be empty/cleared after recovering from the exception. This is causing missing data inserts/updates. Please help me with this.
Summary:
Retry the preparedstatement batches if an exception (SQLException | BatchUpdateException) occurs
Current Implementation:
do {
try {
if (isInsert) {
int[] insertRows = psInsert.executeBatch();
psInsert.clearBatch();
System.out.println("insertRowsSuccess:" + Arrays.toString(insertRows));
} else {
int[] updateRows = psUpdate.executeBatch();
psUpdate.clearBatch();
System.out.println("updateRowsSuccess:" + Arrays.toString(updateRows));
}
break;
} catch (BatchUpdateException e) {
conn.rollback();
if (++count == maxTries) {
System.out.println(e.getMessage());
getFailedRecords(e, operation);
}
} catch (SQLException e) {
if (++count == maxTries) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
System.out.println("Tries:" + count);
} while (true);
private static void getFailedRecords(BatchUpdateException ex, String operation) {
int[] updateCount = ex.getUpdateCounts();
ArrayList<Integer> failedRecsList = new ArrayList<Integer>();
int failCount = 0;
for (int i = 0; i < updateCount.length; i++) {
if (updateCount[i] == Statement.EXECUTE_FAILED) {
failCount++;
failedRecsList.add(i);
}
}
System.out.println(operation + " Failed Count: " + failCount);
System.out.println(operation + " FailedRecordsIndex:" + failedRecsList);
}
After execute, irrespective of success or failure of the batch, the batch will be cleared. You will need to repopulate the batch before you can retry.
I think you should just move the clearBatch() outside of the try. If you have to recheck whether it's an insert or update, so be it. If psInsert and psUdate are the same class, or derive from the same base class (and it sounds like they should), you can easily call it in a separate one liner method.
I also think if you submit this question to code review, you'd get some good suggestions to improve the code. I'm not saying it's terrible, but I think there's room for improvement in the underlying model. I'm not familiar enough with Java, though.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
So I have an issue. My RPC calls will fail due to "NullpointExeption". Meaning that one column contains null in value. This is done on purpose, as I am gonna fill this column with value at some time. How can I allow the Java code to ignore/ or allow this error to happen thru error handling??
#Override
public List <BreakRegistered> getAllRegisteredBreaks() throws IllegalArgumentException {
List<BreakRegistered> resultsfromquery = null;
ResultSet resultSet = null;
try {
//Execute query kaldes på resultsetter, fordi der kun nedhentes data
resultSet = getAllEmployeesBreaks.executeQuery();
resultsfromquery = new ArrayList<BreakRegistered>();
while (resultSet.next()) {
resultsfromquery.add(new BreakRegistered(
resultSet.getTimestamp("time").toString(),
resultSet.getTimestamp("checkedOut").toString(), //Error occurs HERE!
resultSet.getString("navn"),
resultSet.getInt("medarbejderID")));
}
} catch (SQLException sqlException) {
throw new IllegalArgumentException(" \"getBreaks\" fejlede");
} finally {
try {
resultSet.close();
} catch (SQLException sqlException) {
sqlException.printStackTrace();
close();
}
}
return resultsfromquery;
}
The implication is that resultSet.getTimestamp("checkedOut") is returning null. You need to check for that before you try to deference the object to call toString().
A typical construct for this might be:
Object time = resultSet.getTimestamp("checkedOut"); //Or use a more specific type
String timeAsString;
if ( time != null)
timeAsString = time.toString();
else
timeAsString = null; // or empty string, or any other placeholder value you want
P.S. It looks like you are executing SQL queries. I would not call those "RPC calls".
You just need to check whether it is null. If you will use this query result later, It would be nice to put the logic into Object. Moreover, In this case, you just need to change the constructor if there will be some changes to your DB in the future.
public BreakRegistered(ResultSet resultSet) {
this.time = resultSet.getTimestamp("time") != null ? resultSet.getTimestamp("time").toString() : null;
this.checkedOut = resultSet.getTimestamp("checkedOut") != null ? resultSet.getTimestamp("checkedOut").toString() : null;
this.navn = resultSet.getString("navn");
this.medarbejderID = resultSet.getInt("medarbejderID")
}
i am a student and right now I'm doing an internship working with a local library, and in this case i have the following problem:
In the project i´m making, i need to retrieve image data from a temporal table, constructed in ORACLE that receives its data from some triggers in an INFORMIX DB and parse it through a monitor made in JAVA, in a JSON format to a web service published in C# and insert that image in a SQL Server DB.
I looked around and i found that it was possible to parse images through JSON using Base64 encoding and whatnot but when they talk about it they say that you must have the image path file and encode it. as you may have realized by now, i cant use that route because i don't have those images, best case scenario, the triggers are able to feed some BLOB data (by what I've been told). but i have to insert them in the SQL Server DB as Varbinary(MAX).
To summarize:
-->Informix DB has images -->triggers feed an ORACLE Temp_table (images sent probably as BLOB or CLOB at most)-->monitor made in JAVA must read those BLOBS or CLOBS and send them through JSON
-->Web Service made in C# must receive that JSON, and insert the images in a SQL Server DB (where they need to be visible, without having the physical file to refer to).
the schema i´m using (it has been IMPOSED to me, i didn't had a saying in this) is something similar to this: (it´s really long and tedious code so i´ll try to make it as neat and clean as possible)
This is the part of the java monitor that specifies which fields from the temp_table are feeding what fields in the JSON structure
public static BookRecordList viewBookRecordTable(Connection connection) throws ExceptionToOracleConcurrent
{
BookRecordList bookRecordList = new BookRecordList();
BookRecord bookRecord = new BookRecord();
Statement stmt = null;
String query = "SELECT operacion,"
+ "UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(img_logo,32670,1))"
+ "x_logo,"
+ "UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(img_logoGris,32760,1))"
+ "UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(r_firma,32670,1)),"
+ " FROM "
+ dataBaseConnectionData.getDB_SHCHEMA() + "."+ dataBaseConnectionData.getDB_TABLE_COLA()
+ " WHERE (some condition)";
try
{
stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
while(rs.next())
{
try
{
bookRecord = new BookRecord();
bookRecord.setOperacion(rs.getInt("operacion"));
bookRecord.setImg_logo(rs.getString("img_logo"));
bookRecord.setImg_logoGris(rs.getString("img_logoGris"))
bookRecord.setR_firma(rs.getString("r_firma"));
bookRecord.print();
bookRecordList.getBookRecordList().add(bookRecord);
}
catch (Exception e)
{
logger.error("Some exception " + dataBaseConnectionData.getDB_TABLE_COLA() + ": " + e.toString());
e.printStackTrace();
//Process next order
continue;
}
}
}
catch (SQLException e )
{
logger.fatal("Some exception " + dataBaseConnectionData.getDB_TABLE_COLA() + ": " + e.toString());
throw new ExceptionToOracleConcurrent("exception definition " + dataBaseConnectionData.getDB_TABLE_COLA() + ": " + e.toString());
}
finally
{
if (stmt != null)
{
try
{
stmt.close();
}
catch (SQLException e)
{
logger.fatal("another exception " + e.toString());
}
}
}
return bookRecordList;
}
This is the part of the java monitor that generates the JSON (the empty cases contain another stuff that goes into the JSON but i sorted that out)
private static String GenerateJSON(SomeClass someClass) throws IOException
{
int operation = someClass.getOperation();
JSONObject obj = new JSONObject();
String jsonText = "";
switch (operation)
{
case 0:
//obligatory fields
obj.put("img_logo",someClass.getImg_logo());
break;
case 1:
break;
case 2:
//Obligatory fields
obj.put("img_foto",someClass.getC_empleado());
obj.put("img_firma",someClass.getC_empleado());
break;
case 3:
obj.put("r_firma",someClass.getR_firma());
break;
case 4:
break;
case 5:
break;
}
StringWriter out = new StringWriter();
obj.writeJSONString(out);
jsonText = out.toString();
String newJson = jsonText.replace("\\/", "/");
logger.info("JSON a enviar: " + newJson);
return newJson;
}
The web service is made in C#, it´s another case based program, structured accordingly to the operation number received in the JSON, it calls a number of function and, in the end, it comes down to these two:
this part of the WS receive the parameters of the parsed JSON
public int ActualizarFichaLibro( String img_foto, String r_firma)
{
try
{
//Define query to insert
Cmd.CommandText = QueryCFA.ActualizarFicha();
//Define parameters types to insert
Cmd.Parameters.Add("#img_foto", SqlDbType.VarBinary, -1);
Cmd.Parameters.Add("#r_firma", SqlDbType.VarBinary, -1);
//Define parameters values to insert
Cmd.Parameters["#img_foto"].Value = img_foto;
Cmd.Parameters["#r_firma"].Value = r_firma;
int rowCount = Cmd.ExecuteNonQuery();
CerrarConexionBd();
return rowCount;
}
catch (Exception)
{
return 0;
}
}
and finally that invokes a simple query, in this particular case, to this one:
public string ActualizarFicha()
{
Query = "UPDATE dbo.fichaEmpleado SET( CASE WHEN #img_foto = '' THEN NULL ELSE img_foto = CONVERT(VARBINARY(MAX), #img_foto, 2) END,"
+ "CASE WHEN #r_firma = '' THEN NULL ELSE img_firma = CONVERT(VARBINARY(MAX), #r_firma, 2) END,"
+"WHERE (some conditions)";
return Query;
}
my questions are:
is there a way to do this (sending images from one DB to anther) through JSON, specifically with this massive schema this people got going on? if not is there a way to do it?
the querys for reading a BLOB (possible BLOB) and inserting a Varbinary are well implemented?
I´m sorry for the extremely long explanation, I've been working on this for a week and i cant seem to find a proper way to do it (at least not with this schema, but the bosses don't want to change it)
Here is what I am trying to do (for over a day now :( A user clicks on a link of a book name and I read the name of that book. I then take that book name and make an Ajax request to a Jersey resource. Within that Jersey resource, I call a method in a POJO class where one method interacts with database and gets the data to be sent back to a Jersey resource. I have got many errors but I have been able to fix them one at a time. The error currently I am stuck at is:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1
Here is my JavaScript code:
function dealWithData(nameOfBook){
var bookName = encodeURI(nameOfBook);
console.log("http://localhost:8080/library/rest/books/allBooks/"+bookName);
var requestData = {
"contentType": "application/json",
"dataType": "text",
"type": "GET",
"url": "http://localhost:8080/library/rest/books/allBooks/"+bookName
**//beforeSend has been added as an edit to original code**
beforeSend: function (jqXHR, settings) {
var theUrlBeingSent = settings.url;
alert(theUrlBeingSent);
}
};
var request = $.ajax(requestData);
request.success(function(data) {
alert("Success!!");
});
request.fail(function(jqXHR, status, errorMessage) {
if((errorMessage = $.trim(errorMessage)) === "") {
alert("An unspecified error occurred. Check the server error log for details.");
}
else {
alert("An error occurred: " + errorMessage);
}
});
}
For some reason in above code, console.log line shows url with spaces being encoded as %20 while in the variable 'requestData', url doesn't have that encoding. I am unable to understand why.
Here is the code for my resource:
#GET
#Path("/allBooks/{bookName}")
#Produces(MediaType.APPLICATION_JSON)
public Response getBook(#PathParam("bookName") String bookName){
System.out.println("Book name is: "+ bookName);
BookInformation bookInfo = new BookInformation();
String bookInformation =bookInfo.bookInformation(bookName);
ResponseBuilder responseBuilder = Response.status(Status.OK);
responseBuilder.entity(bookInformation);
Response response = responseBuilder.build();
return response;
}
Here is the bookInformation method:
public String bookInformation(String bookName){
String infoQuery = "Select * from bookinfo where name = ?";
ResultSet result = null;
conn = newConnection.dbConnection();
try
{
preparedStatement = conn.prepareStatement(infoQuery);
preparedStatement.setString(1, bookName);
result = preparedStatement.executeQuery(infoQuery);
}
catch (SQLException e)
{
e.printStackTrace();
}
try
{
if(result != null){
while(result.next()){
availability = result.getString("availability");
isbn = result.getInt("isbn");
hardback = result.getString("hardback");
paperback = result.getString("paperback");
name = result.getString("name");
}
}
else{
System.out.println("No result set obtained");
}
}
catch (SQLException e)
{
e.printStackTrace();
}
//I will build this String using a String builder which I will return
String finalBookInformation = information.toString();
return finalBookInformation;
}
Earlier, in dataType I had json which was throwing a different error, but I realized I was not building json so I changed dataType to text and that error went away. My parametirized query doesn't execute. If I try hard coding a value from database, it works fine but not when I use prepared statement. I eventually want to return JSON but for now I just want it to work. Any help will be appreciated. I have tried researching and doing whatever I can but it is not working. Is it the encoding causing the problem? Is it my Ajax call? Any help is appreciated. Thanks.
Seems like issue is in your database query execution please replace the code
preparedStatement = conn.prepareStatement(infoQuery);
preparedStatement.setString(1, bookName);
result = preparedStatement.executeQuery(infoQuery);
with
preparedStatement = conn.prepareStatement(infoQuery);
preparedStatement.setString(1, bookName);
result = preparedStatement.executeQuery();
You are using HTTP GET method and GET method automatically %20 if find space in url.
If you change your method type to POST It should work find for you.
You can use HTTP GET but it will encode the URL as you discovered. You will need to decode the URL on the server-side. For how to do that, take a look at: How to do URL decoding in Java?.
in my app searchbar is there, wheren in user types the text. Whenever a text get changes in the filed i will call a query to DB to get the related search items. But sometimes it crashes.
Here is the code i'm doing to call DB
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
if(newText.trim().equals(""))
{
return false;
}
//showSearchSuggestions(newText);
mfilterdata = mController.get_controllerObj().getDBManager().getAllSuggestedFilter(newText);
if(mSearchadapter != null)
mSearchadapter.swapCursor(mfilterdata);
return false;
}
Here is how i m querying in DB manager
public Cursor getAllSuggestedFilter(String filterString)
{
String READ_QUERY = "SELECT * FROM " + Tbl_ITEM_TABLE + " where "+
item.TITLE + " Like" + "\"%" + filterString + "%"+"\"";
if(mcursorForFilter != null)
{
mcursorForFilter.close();
mcursorForFilter = null;
}
try
{
mcursorForFilter = getReadableDatabase().rawQuery(READ_QUERY, null);
}
catch(Exception ee)
{
}
return mcursorForFilter;
}
randomly i get exception like
java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT * FROM itemtable where title Like"%t%")
That's probably because you are closing the cursor in the wrong place, and trying to use it after that, but you cannot use an already closed cursor.
I would get rid of this part of the code:
if(mcursorForFilter != null) {
mcursorForFilter.close();
mcursorForFilter = null;
}
Instead, close the old cursor after you set the new one. swapCursor() returns the old Cursor, or returns null if there was not a cursor set, also returns null if the if you try to swap the same instance of the previously set cursor. Knowing that, you can try something like this:
Cursor c = mSearchadapter.swapCursor(mfilterdata);
if(c != null)
c.close();
Try that, and let me know if that helped.
Note that when you are using a Loader (LoaderManager.LoaderCallbacks), the framework is going to close the old cursor. This is what the documentation says:
onLoadFinished:
The loader will release the data once it knows the application is no
longer using it. For example, if the data is a cursor from a
CursorLoader, you should not call close() on it yourself. ...