this is going long in my mind, i still wonder why spring jdbc made EmptyResultDataAccessException as runtime exception instead of forcing calling method (by making Exception) to catch a EmptyResultDataAccessException, i personally faced an issue , when i first implement spring jdbc, let us take this first scenario
public List<User> getUsers(String firstName){
JdbcTemplate jd = this.getJdbcTemplate();
List<User> userLst = jd.query("select query for user here matched firstname", BeanPropertyRowmapper(User.class))
}
in the above scenario even if this select query doesnt return any value, spring jdbc still creates new List object of type user and returns list object with size 0. so here spring jdbc is not throwing EmptyResultDataAccessException , instead it is creating new List object if there is no rec fetched from DB.
secondly, in case for querying for an object, it behaves differently.
User user = jd.queryForObject("select * from user where user_id = [EDITuser id here", User.class)
here spring jdbc throws EmptyResultDataAccessException incase it didnt find any record for *user_id = 1*.
more over, since EmptyResultDataAccessException is runtime exception, i was not forced to catch this exception and do some action for this exception, so most of time developer puzzled and it go unnoticed.
as i said in the first scenario , when i first coded, i was expecting userLst object as null, but actually spring jdbc creates new object which we didnt handle it.
posting this to make myself clear on this aspect. Thanks
There is most probably no way to make everyone happy. Take the contrary, you perfectly know that the row exists because it's a valid ID. Yet, calling this method forces you to catch this exception that will never be thrown so you have an empty catch block, which is bad.
This goes back to the use of runtime exception vs. checked exception, there are plenty of references on this site and elsewhere.
Related
I am working on play framework using jpa, I have a field with an unique constraint, after "try" to persist an entity with a repeated value, the framework shows an error page like this:
error page
When I try to catch this exception...
try{
JPA.em().persist(nArtist);
}catch(Exception e){
form.reject("username","user already exist");
return badRequest(create_artist.render(form));
}
The page still shows the message... ( I tried already with rollback exception ).
Pdta: That JPA.em() is the only time I called the em.
The call to EntityManager.persist does not guarantee changes to be flushed to the database immediately (which is the point at which constraint violations would emerge). If you want to force a flush, call EntityManager.flush right after persist
Do not use exceptions to handle conditions that could normally occur in your application and, above all, do not use the generic java.lang.Exception. The exceptions thrown from the persistence layer at persist time could mean a lot more things than the specific constraint violation that you're after
I am working on a spring MVC application. I have a DAO, Service and Controller. In Dao, I have a method which queries database to return a Sql rowset. I am checking sql rowset to be empty and if it is, I am throwing a Runtime exception. Also, according to the logic of the application, the query to database should return at least one row. So, basically I am assuming that if I get an empty sql rowset, then there is some issue, may be database is corrupt or something similar.
Is this the correct way to check for unknown exceptions. Or should I return the sql rowset as it is to the service? It may result in a null pointer exception when service uses this sql rowset.
The problem is if I throw exception in dao, I can't cover that part in the test cases. Means I have to put db in inconsistent state for this code to execute and test the exception handling part.
No, more generally you should never introduce a restriction into your application just because you don't have that situation or requirement right now. If you don't have any rows in a database your database might just be empty... Or you may be doing testing on that schema and it is currently empty. Your violating the concern of the dao by doing that.
Furthermore don't worry about the database, that is senseless. If you can't accept the tools you are working are functioning correctly then you won't be able to build anything at all. If you want to handle database exceptions have a controller which catches these exceptions and redirects to a view showing an error message:
#ControllerAdvice
public class ErrorHandler {
#ExceptionHandler(DataAccessException.class)
public String handleDatabaseException(DataAccessException ex) {
return "error";
}
#ExceptionHandler(CannotCreateTransactionException.class)
public String handleAccessException(CannotCreateTransactionException ex) {
return "database_error";
}
}
The DAO layer should not concern itself with business rules. It should simply abstract the data operations so that the service layer does not need to concern itself with how and where is the data being stored.
In my opinion, the DAO should simply return an empty result set. It will be up to the service to know what to do with an empty result set, since at the service layer is usually where the business logic is stored.
We are using mySQL + JDO + Datanucleus.
When I call pm.getObjectById(type,id); it throws the exception
javax.jdo.JDOUserException: Failed to find the object of with id "org.geppetto.persistence.db.model.GeppettoProject:1"
NestedThrowables:
org.datanucleus.exceptions.ClassNotResolvedException: Class "org.geppetto.persistence.db.model.GeppettoProject" was not found in the CLASSPATH. Please check your specification and your CLASSPATH.
However if before calling it I query the database with something like the following
Query query = pm.newQuery(GeppettoProject.class);
query.execute();
then from that moment on getObjectById starts returning the object. Is this behaviour correct? getObjectById seems to only return things once they are cached, i.e. only after a query was executed.
In general I wouldn't like to have to bother with this, if things have to be fetched for the first time then let it be, if they were already fetched give me whatever is cached but I wouldn't expect to have to know about it. Am I missing something?
I'm using JPA 2 with the Hibernate ver. 4.1.7.Final as JPA implementation. I'm also using Spring framework v. 3.1.2.RELEASE to be clear. And here is my problem.
I have written a method to add/update my User entity.
#Override
#Transactional
public void saveUser(UserForm userForm) {
User user;
if (userForm.getId() == null) { // new user
user = new User();
user.setCreationDate(new Date());
entityManager.persist(user); // !!!
} else {
user = entityManager.find(User.class, userForm.getId());
}
user.setFirstName(userForm.getFirstName());
user.setLastName(userForm.getLastName());
user.setMiddleName(userForm.getMiddleName());
user.setEmail(userForm.getEmail());
user.setRole(entityManager.find(Role.class, 1));//TODO
user.setLogin(userForm.getLogin());
user.setPassword(userForm.getPassword1());
entityManager.flush();
}
I'm testing addition of user (userForm.getId() == null). And the above code doesn't work, giving error:
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Column 'first_name' cannot be null
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1306)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:989)
...
But. If I move call to persist() to the end before flush() all works fine:
#Override
#Transactional
public void saveUser(UserForm userForm) {
User user;
if (userForm.getId() == null) { // new user
user = new User();
user.setCreationDate(new Date());
} else {
user = entityManager.find(User.class, userForm.getId());
}
user.setFirstName(userForm.getFirstName());
user.setLastName(userForm.getLastName());
user.setMiddleName(userForm.getMiddleName());
user.setEmail(userForm.getEmail());
user.setRole(entityManager.find(Role.class, 1));//TODO
user.setLogin(userForm.getLogin());
user.setPassword(userForm.getPassword1());
entityManager.persist(user);// !!!
entityManager.flush();
}
I think what happens is in first (problem) case it tries to store the User object data existed at time of persist call, although the actual save executed during flush() (upd. Wrong. It tries to issue sql insert exactly at persist() call). What make me think this way is when I tried to debug I have found that it still tries to insert correct creation_date somewhere inside, but other values are nulls.
But I swear that in my other project I've been working on some years ago this worked just fine, though then I used Oracle instead of MySQL (I don't think this is the reason) and older versions of frameworks.
What could be the problem here? Maybe there is some configuration option for Hibernate affecting this?
Or this is the correct behaviour and my misunderstanding of JPA API?
UPD. I'm using
#Id
#GeneratedValue
#Column(columnDefinition="INT")
private int id;
for id field in User entiry. I believe it means generation strategy = AUTO, which is appropriate for mysql auto_increment key.
You set your user first name to null (user.setFirstName(userForm.getFirstName());) because userForm.getFirstName() returns null, and your error displays that: Column 'first_name' cannot be null.
You should check why userForm.getFirstName() returns null or allow user's first name to be null because your current entity configuration does not allow that.
Maybe you could show us User entity?
Thats correct behaviour. At the time of your first call persist(), user's firstName is null. Enventhough you have set the first name after this point, but before the flush, JPA/Hibernate prepared commands would be something like,
At the time of persist, the state of user object lets say, user#version1
Insert into user values (id, creationdate, null, null..) from user#version1 object
Now a new user version exists user#version2
At the time of flush,
check for any pending inserts/updates.. bring all the objects to version1, which is at the time of last persist.
Note that, flush may or may not do physical insert operation in DB, but the objects are are brought to the correct state, meaning non persisted changes would be lost.
Dont worry if it was working fine before may be with hibernate 3, and started not working when you migrated to hibernate 4. I have several issues, where hibernate 3 is no problem, but doesnt work on hibernate 4 without additional fixes.
I learnt Hibernate and used it to reduce my Java code to a vast extent and also able
to reduce the time spent for DB's. Now what type of query should i use to finish my
operations for getting a DB list to be displayed, to update and delete.
My code for deletion is
String newToken = "DELETEUSER";
if(!TokenManager.checkRoleToken(newToken)){
return;
}
Session session = Main.getSession(); //calling the main method to get sesion
Leavetable table = new Leavetable; // intialisation of object table
try{
Transaction tr = session.beginTransaction();
table = session.createQuery();
session.delete(table); // deletion of the object and its properties from selected leaveID
tr.commit();
}
finally{
session.close();
}
My code for Db updation
public void updateLeaveTable( Leavetable leave ) {
String newToken = "ADDUSER";
if( !TokenManager.checkRoleToken( newToken ) ) {
return;
}
Session session = Main.getSession(); // calling the main method to get
// session
try {
session = Main.getSession();
Transaction tr = session.beginTransaction();
session.saveOrUpdate( leave ); // here without query the table gets
// updated How?
tr.commit();
}
finally {
session.close();
}
}
What type of query should I follow. My final task before going into project. When I
know this will start my life as a developer. Any suggestions Please.
Do you mean a HQL query? Well, a typical query on your Leavetable entity would looks like this:
Query q = session.createQuery("from Leavetable t where t.someField = :value");
q.setParameter("value", foo);
List<Leavetable> results = q.list();
However, if you just want to retrieve an entity by identifier, see Session#load() or Session#get(). I don't want to make things too much confusing but while both methods are similar, there is an important difference between both of them. Quoting the Hibernate Forums:
Retrieving objects by identifier
The following Hibernate code snippet
retrieves a User object from the
database:
User user = (User) session.get(User.class, userID);
The get() method is special because
the identifier uniquely identifies a
single instance of a class. Hence it’s
common for applications to use the
identifier as a convenient handle to a
persistent object. Retrieval by
identifier can use the cache when
retrieving an object, avoiding a
database hit if the object is already
cached. Hibernate also provides a
load() method:
User user = (User) session.load(User.class, userID);
The load() method is older; get() was
added to Hibernate’s API due to user
request. The difference is trivial:
If load() can’t find the object in
the cache or database, an exception is
thrown. The load() method never
returns null. The get() method
returns null if the object can’t be
found.
The load() method may return a proxy
instead of a real persistent instance.
A proxy is a placeholder that triggers
the loading of the real object when
it’s accessed for the first time; we
discuss proxies later in this section.
On the other hand, get() never
returns a proxy.
Choosing between get() and load()
is easy: If you’re certain the
persistent object exists, and
nonexistence would be considered
exceptional, load() is a good
option. If you aren’t certain there is
a persistent instance with the given
identifier, use get() and test the
return value to see if it’s null.
Using load() has a further
implication: The application may
retrieve a valid reference (a proxy)
to a persistent instance without
hitting the database to retrieve its
persistent state. So load() might
not throw an exception when it doesn’t
find the persistent object in the
cache or database; the exception would
be thrown later, when the proxy is
accessed.
Of course, retrieving an object by
identifier isn’t as flexible as using
arbitrary queries.
See also the Hibernate Documentation (links below).
Reference
Hibernate Core Reference Guide
10.3. Loading an object
Chapter 14. HQL: The Hibernate Query Language