i have created a namedquery with ejb to check if the username is used.
When the singleResult is null, then i get the following Exception :
javax.persistence.NoResultException: getSingleResult() did not retrieve any entities
But this exception is the result that i want when the username is free.
Here is the code:
public User getUserByUsername(String username) throws DAOException{
try{
Query q = em.createNamedQuery(User.getUserByUsername);
q.setParameter("username", username);
return (User) q.getSingleResult();
}catch(Exception e){
throwException(username, e);
return null;
}
}
Does anybody know what the problem is. :(
I would like to return null and don`t get an Exception.
Thank you very much
You seem to rethrow the exception in your catch block with the statement throwException(username, e);. If you expect to get the user or null without any exception this should look like the following:
public User getUserByUsernameOrNull(String username) {
try{
Query q = em.createNamedQuery(User.getUserByUsername);
q.setParameter("username", username);
return (User) q.getSingleResult();
} catch(NoResultException e) {
return null;
}
}
Use getResultList instead and check if the List is empty (has zero element). Otherwise, the list contains one element and you simply return it.
You experience the defined behaviour when calling getSingleResult and none entry was found: A NoResultException is thrown. You can catch NoResultException in the catch-clause, because the transaction won't be marked as rollback, when JPA is throwing NoResultException. Or you can use getResultList() and check if size is exactly "1", so you know you have found your user.
Additionally, I wouldn't return "[null]" if the user is not found, but throw a checked UserNotFoundException (to be defined). But this depends on the contract of the method you are going to implement.
Michael said: "You can catch NoResultException in the catch-clause, because the transaction won't be marked as rollback, when JPA is throwing NoResultException.". It looks like for some jpa implementations, the NoResultException will rollbak transaction, which violates jpa specification, according to this article: NoResultException marks transaction rollback
If your application uses Spring Roo the most voted answer doesn't work: the exception is caught by the aspects and you never get the desired NoResultException.
The only way to solve the issue is to use getResultList and to check for zero, one or more results in the resulting List, as stated in the second most voted answer.
try {
Query queryObj = entityMgrObj
.createQuery("SELECT u FROM UserEntity u WHERE u.email = :email AND u.password = :password");
queryObj.setParameter("email", email);
queryObj.setParameter("password", password);
UserEntity userEntity = (UserEntity) queryObj.getSingleResult();
return userEntity;
} catch (NoResultException e) {
return null;
}
What does the method throwException do?
Is an exception being thrown within it but you are using the prior exception's message?
Catch NoResultException in try-catch block and handle it as per your requirement such as returning a null value.
Example of try-catch is detailed in the following link:
http://www.javabrahman.com/j2ee/jpa/no-result-exception/
Related
I have a hibernate fetch as follows (it is called by a synchronized method in threads). The problem is if I updated the status_id to 1 in the DB console, the code won't pick it up. And when I run the sql Hibernate show_sql printed out in the console, it can find one record. Moreover, I can see the select sql being run every time via show sql.
To make the problem clear, if I update the record status to 1 and then start the application, the code will return me one record and after processing, the record status will be updated to 2. As I expected, after that, the code will return nothing cause the status being updated to 2. However, if I manually update the status to 1, it won't pick it up.
As you can see from the configuration, I have already turn off the 2nd level cache and every time, I close the session. I am using Enum to define the Hibernate connection. So the sessionFactory is always the same instance. I don't know if this matters but I assume that is what it should be.
The dao code is
Session session = null;
String sql = "from MyEntity rr where status_id = 1;"
try {
session = getSessionFactory().openSession();
Query q = session.createQuery(sql);
q.setMaxResults(1);
List resultList = q.list();
if (resultList.isEmpty())
return null;
return (MyEntity) resultList.get(0);
} catch (Exception e) {
LOGGER.error(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
return null;
The code to update the status is
Session session = null;
try {
session = getSessionFactory().openSession();
session.beginTransaction();
session.update(myEntity);
session.flush();
session.getTransaction().commit();
} catch (Exception e) {
LOGGER.error(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
If the entity doesn't exist, you need to invoke save() on it, otherwise you need to invoke update(), it will modify the existing persistent object in database.
Be aware everytime invoke save() would insert a new row in database. You may use saveOrUpdate() to achieve above save() and update() actions, Hiberate will either call save or update depends on the situation and take care of it.
You can invoke flush() after each saveOrUpdate() which forces Hibernate execute save or update in your database.
I found the solution. Once I put the transaction on fetch, it start to work. Don't know why. Any one can give some explaination? Thanks.
I am trying to retrieve records from oracle database for the SQL query - SELECT data FROM test where id = ?;
Here is my code to retrieve the data -
public static String retrieveData(String id) throws IOException {
String result = "";
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT data FROM test where id = ?";
connection = getDBConnection(); //this method gets the db connection
ps = connection.prepareStatement(sql);
ps.setString(1, id);
rs = ps.executeQuery();
while(rs.next()) {
result = result + rs.getString("data");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeDBConnection(); //closes db connection
}
return result;
}
When I invoke the retrieveData in the main method, it returns null. When I debug, the resultSet is empty. I am guessing the reason is I am passing my id as String, but perhaps Oracle doesn't understand something like - SELECT data FROM test where id = "1234567890";
Can someone please guide me how do I fix this? I have tried way too many things, but I can't seem to fetch the data from the db for this id. I also tried converting the id to long using Long.valueOf(String s).longValue(); and setting this as the placeholder in ps.setLong, but it didn't help. Please advise.
Type issue of id column
This is probably due to spacing difference or another subtle difference that gives the impression that they are the same.
The strings ' 123 ' or '00123' (for example) are not equivalent to '123' in VARCHAR2 type, while they are equivalent in NUMERIC type, as Oracle converts all those strings to the numeral 123.
You are better off using a NUMERIC column as your id to avoid such problems. It also makes sense to limit your valid id values to whole numbers, rather than any arbitrary string.
With Oracle you can continue to use setString as it will automatically cast the string to an integer. But I recommend you to use setInt or setLong instead (after the conversion of the id column), as other database solutions like Postgres will not accept a string to match a NUMERIC column.
Exception handling issue
When you catch a Throwable or an Exception (or their subtypes), be sure to think about whether it can be ignored, or it must be thrown for further handling (for example, to stop the program, alert the user or correct the problem).
In your code, the catch block catches the SQLException and prints the stack trace. But it doesn't do anything else.
} catch (SQLException e) {
e.printStackTrace();
} ...
This means that you are ignoring the exception and continuing the program as though nothing happened. The execution will continue on to return result; after completing the finally block.
The caller of your method will never know that an SQLException occurred, and it will wrongly assume that there were no errors and the returned data is correct.
Unless that is what you really want, what you ought to do is as follows:
} catch (SQLException e) {
e.printStackTrace(); //it doesn't matter what you do here. the next line is what's important.
throw e; //throw the exception after printing stack trace, logging, etc.
} ...
In this case your method will throw the SQLException to the caller after completing the finally block. The execution will not continue to return result;.
This way the caller of your method will receive the exception and know that an error has occurred. The caller can then act accordingly; for example, by stopping the program, alerting the user or retrying the method with a different input.
may be the reason is DEBUG. if you have a breakpoint on the line "while(rs.next())" and you watch/inspect it then then rs increments one. Then the code executes rs.next for the second time where there is no record.
maybe...
You shouldn't use datatype 'String' for id field, it can cause serious trouble. Try to covert it to numeric datatype is possible but why don't you use numeric at first. You should change to int or bigint. In additional try to catch exception like this:
try{
}catch(SQLException ex){
System.out.println("Error at:" +ex.getClass().getName() + ex.getMessage());
}
Try it again, if you can't debug it and find out why! Good luck!
Please try this. Remove all the spaces when defining field name with a ? and check
SELECT data FROM test where id=?
public UserBean authenticate(String username,String password){
PostGresDAO pg=new PostGresDAO(); //creates new connection
Connection conn=pg.getConnecion(); //return connection object
PreparedStatement ps;
ResultSet rs;
String query="select password,name from scg_users where username=?";
UserBean ub=null;
boolean authenticated=false;
try{
ps=conn.prepareStatement(query);
ps.setString(1, username);
rs=ps.executeQuery();
if(rs!=null){
authenticated=password.equals(rs.getString(1)); //exception raised here
if(authenticated){
ub=new UserBean();
ub.setUser(rs.getString(2));
ub.setUsername(username);
}
}
}
catch(SQLException e){
e.printStackTrace();
}
return ub;
}
I am using this code for authenticating a user. The username and password are extracted from the request parameter and passed onto this method for authentication. But it throws a:
org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next.
Please advice.
The error is telling you exactly what's wrong - you're not calling next() on your ResultSet to get to the first row of the results.
This line:
if(rs!=null)
is pointless as far as I know; I don't believe executeQuery will ever return null. If there's a problem in your query, an exception will be thrown. If there are no results, it will return an empty result set. To see if there's a row, you should call next() and check the return value:
if (rs.next())
Additionally:
Catching an exception and just printing the stack trace without rethrowing is almost always the wrong approach
Your code suggests that you're storing passwords in plain text. Please don't. Really, really don't.
Because I got the message even when I called next() on resultSet I'll tell my solution.
The solution is NOT to call resultSet.get* on your resultSet if it's empty. So do a check if(resultSet.next()){ ...
Instead of
if(rs!=null)
You need to check for
if(rs.next())
This will return the first row, if there are any matching rows.
Maybe you have resultSet.next() in debugger Inline Watches :)
It was the case for me;
So my check if (resultSet.next()) returns true but when I go inside the if block, the next() is called again and then there is no data so I got the same error message
Consider the below two codes.
Session session = null;
query = "update Employee set EMPLOYEE_NAME = 'Jay' where EMPLOYEE_ID = 1";
try {
session = getSession();
Query query = session.createSQLQuery(dlquery);
query.executeUpdate();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if(session != null) {
releaseSession(session);
}
}
And....
Session session = getSession();
query = "update Employee set EMPLOYEE_NAME = 'Jay' where EMPLOYEE_ID = 1";
try {
Query query = session.createSQLQuery(dlquery);
query.executeUpdate();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if(session != null) {
releaseSession(session);
}
}
Which among the two is better to use? Or is there a better way? What wrong I might be doing here?
Also should we do a null check before calling releaseSession(session) in finally?
Truly, the best way is to leverage Spring and its JPA/Hibernate support.... You'll never have to deal with it in your code.
To be honest, I'd say there wasn't much difference at all in the two, but you should always check if the session is null, just so you don't cause another NullReferenceException.
Unfortunately this is probably the cleanest way to do this in Java, as there is no such thing as the "using" statement as there is in C#, which allows you to dispose the object after the using block has finished executing.
I would suggest using a transaction. If tomorrow you change your code to add another update for instance, you won't have to worry about any consistency problem in case something happens while executing an update. Aside from that, I would suggest using parameters in your query rather than hard-coding the values. This way you could reuse the query.
If getSession() throws an Exception for some reason, would not it be problem in second solution?
Use the below syntax to get and release session.
session = getSession();
Query query = session.createSQLQuery(dlquery);
query.executeUpdate();
session.close();
I was working on a servlet that will generate a unique code and update that in a mySQL database.
Now, in that, I want to catch any exception thrown in case that unique code already exists in the mySQL table and generate a new code and try updating the database. The problem is I want to do this WITHIN the for loop itself. The code is as follows:
try
{
connection = datasource.getConnection();
SQLUpdate = "INSERT INTO Voucher_dump VALUES( '"+unique_code+"','08-10-2011 04:48:48','0')";
PreparedStatement ps1 = connection.prepareStatement(SQLUpdate);
ps1.executeUpdate();
ResultSet r = ps1.getResultSet(); // this is where I'm checking if it's a duplicate
if(r==null)
out.println("This is a duplicate");
else out.println("Updated");
trial12= "08-10-2011 04:48:480.03999855056924717a";
SQLUpdate = "INSERT INTO Voucher_dump VALUES( '"+trial12+"','08-10-2011 04:48:48','0')";
ps1 = connection.prepareStatement(SQLUpdate);
ps1.executeUpdate();
r = ps1.getResultSet();
if(r==null)
out.println("This is a duplicate");
else out.println("Updated");
}
catch (SQLException sqle)
{
sqle.printStackTrace();
}
I don't want to wait till the end of the entire loop to catch the SQLException (I have already defined this key in mySQL as primary). The moment, the result comes back as a duplicate entry, I want to re-generate this key and attempt the update again.My output for this particular code is coming blank on my output page (all other parameters are showing correctly). Neither is "This is a duplicate" displayed nor is "Updated". Maybe, ResultSet is not the best way to do it. Could you guys give me some advice on what would be the best way forward ?
Some advice in no particular order:
Close the connection in a finally block.
Close statements individually if you'll be creating many of them before closing the connection. ("Many" is defined by your DBAs.)
Format your code.
Don't use stdout and/or stderr from real code. Pick a logging framework.
Consider using some helper classes to simplify (and correct) your database access, like Spring's JdbcTemplate.
Make sure to include relevant context when you post example code.
Due to #6, I don't know what out is, but I suspect the reason you're not seeing anything is that you're inserting a duplicate value with the first statement, which will cause a SQLException from that line, not at getResultSet(), where you seem to expect it. Since the error is written to stdout, it'll show up in your server logs somewhere, but nothing will be written to out. I'm not sure why you think getResultSet() will return null or not null depending on whether there was a constraint violation. Take a look at the javadoc for that method.
Update: 7. As BalusC points out, never, ever concatenate a string directly into a JDBC Statment. Use PreparedStatment's placeholders and set* methods. For info on SQL injection, see Wikipedia and XKCD.
How about this code?
try {
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(url + dbName);
System.out.println("Connected to the database");
int i = 1; //get the unique code
boolean isInserted = false;
while (!isInserted) {
try {
PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO test values (?)");
preparedStatement.setInt(1, i);
preparedStatement.executeUpdate();
isInserted = true;
} catch (com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException e) { //Catch the particular exception which throws error on unique constraint. This may depend on Java/MySQL your version
i++; //get the next unique code
}
}
System.out.println("Disconnected from database");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (Exception e) {
}
}