I am using hibernate as ORM tool, i want to perform some common stuff for all the entities that i flush into the database.
Currently , whenever i save object into database, i perforrm following steps :-
Open session
Begin a Transaction
Create Te Object
save the object using session.save(object);
commit the transaction if save is successfull. otherwise rollback transasction.
close the session.
Now, i want to perform some post-save and pre-flush checks, is there any way to do so.
Thanks.
You can implement 'preFlush' method of Interceptor. Check this for hibernate interceptor.
Related
In my service layer, I am calling a dao class method which is calling
session().get(xyz.class, id);
I am returning the retrieved object back to service class. Then I am updating this object and passing the updated object to dao class update method.
getSession().saveOrUpdate(xyzObj);
But here instead of an update I am getting this exception
org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessions
Please tell me the right way to do a select an update of the same object.
Found the problem.
I was using
sessionFactory.openSession();
to get the session object. So multiple sessions were getting created. Replaced it with
sessionFactory.getCurrentSession();
Now its working fine.
Try closing the first session before getting another one, or use the same session for both operations. As an alternative i think: getSession().merge(xyzObj); should work.
Place all DA operation with the same entity (or entities) into one Service (or named DAO) class, which encapsulate work with Session.
I started working on a new project using Playframework and thought to try using it with Ebean ORM. What i am wondering now is if Play with the Ebean implementation supports managed entities and if so ..how? Take this example method from the controller:
#Transactional
public Result changePassword() {
Long userId = Long.valueOf(session("id"));
User user = User.find.byId(userId);
user.setName("John Doe");
}
Is there any way to persist the changes to the database when the transaction ends? Currently what i am doing is calling user.save(). This is not much but working with JEE/JPA (and recently Dropwizard) i got used to have my entities changes persisted when the transaction ends.
No, I don't think Play natively supports something like auto save transaction as you want. Explicit save method is the only option.
Ebean.save(xyz);
General suggestion on your code, From Play 2.3.x, In your case, No need to annotate or explicitly mention the transaction, if Save is the only action on User EBean. By default each action on EBeans will be executed in separate transactions. Can specify the transaction explicitly if multiple actions need to be executed in single transaction.
Using Hibernate I need to update multiple objects by calling for eg. updateDetails() function shown below:
function updateDetails(){
Session session = this.getSessionFactory().openSession();
Employee emp=(Employee )session.load(Employee.class, empId);
emp.salary(2000);
Account acc=(Account)session.load(Account.class, accId);
account.setTotal(2000);
Transaction tx=session.beginTransaction();
session.update(emp);
session.update(acc);
tx.commit();
result=true;
session.close();
}
what is the best way of doing this ?
does Updating multiple objects of same or different type in same session will cause any problem in hibernate?
Why not. You can do that. Hibernate allows.
Since you are using Transaction management the answer is depends on your context. If you want to save both Objects regardless of saving another make them update in individual transactions.
If you want to save the whole info successfully and want to revert everything if any of the update fail keep them in the current format.
i have a table in mysql which has a data type of timestamp as one of the columns, which gets a default value of CURRENT_TIME upon insertion. and i have another timestamp column that has a default value of CURRENT_TIME upon update. i have these so that timestamp columns will get updated automatically on insertion and update (which works fine).
now i am using cxf, hibernate/jpa, mysql, jackson to build a web service.
i am simply creating a new record and retrieving it right away as below code shows.
Session session = getSession(); // sessionFactory.getCurrentSession();
String accountId = (String)session.save(account);
Account newAccount = (Account)session.load(Account.class, accountId);
logger.info("created timestamp=" + newAccount.getCreatedTimestamp());
after above code is ran, i can see that new record is created in mysql with correct timestamps for createdTimestamp. however, logger.info() line above throws an exception because newAccount.getCreatedTimestamp() returns null. if i remove logger.info() line, i can see that newAccount object is populated with correct values except for createdTimestamp which is null.
what's more odd is that after above code is ran (which is a part of HTTP POST operation), i call a HTTP GET service which just fetches a record that i just inserted by doing
session.get(Account.class, accountId);
and it correctly shows timestamps!
i tried to sleep before session.load() or session.get() thinking that there might be a delay in inserting timestamp, but that didn't do much. is there something special about hibernate session management that does not retrieve columns that mysql generates? what am i missing here? please help.
Your actual save isn't being committed until the session is flushed. Hibernate doesn't actually commit anything to the database until the session is flushed or closed so that if an exception is thrown, a rollback doesn't actually have to touch the physical database, the changes are just not sent. However if Hibernate detects that a query is going to receive stale data, it will automatically flush before running that query.
For example, you add a record to the database and immediately call a SELECT COUNT(*) query. Hibernate will flush the session (committing the record in the process) and then perform the SELECT COUNT(*) query on the now clean session ensuring that you get correct data. Hibernate didn't do this in your case because it saw that you were requesting the same object that you were trying to insert (in the same session) so it just returned you that reference.
If you are letting hibernate manage its sessions (using a session factory or similar) I don't think that you have to explicitly close sessions. I know that I don't, but I'm using Hibernate with Spring, and using the #Transactional annotation which manages the actual Hibernate session. If you want an immediate insert, make your call to save() the last call in the method. Usually, once the method exits, a commit() will be called automatically.
All the load() will be doing is giving you the same instance of Account that you passed into session.save(). Either close or flush the session, then try the load() again, and your value should be set.
Is it possible to stop hibernate from auto updating a persistent object?
#Transactional
public ResultTO updateRecord(RequestTO requestTO) {
Entity entity = dao.getEntityById(requestTO.getId());
// now update the entity based on the data in the requestTO
ValidationResult validationResult = runValidation(entity);
if(validationResult.hasErrors()) {
// return ResultTO with validation errors
} else {
dao.persist(entity);
}
}
Here is what happens in the code, I retrieve the entity which would be considered by hibernate to be in persistent state, then I update some of the fields in the entity, then pass the entity to validation. if validation fails, then don't udpate, if validation succeeds then persist the entity.
Here is the main issue with this flow: because I updated the entity for it to be used in the validation, it does not matter whether I call persist() method (on the DAO) or not, the record will always be updated because hibernate detects that the entity has been changed and flags it for update.
Keep im mind I can change the way i do validation and work around the issue, so I'm not interested in workarounds. I'm interested in knowing how i would be able to disable the hibernate feature where it automatically updates persistent objects.
Please keep in mind I'm using hibernates' implementation of JPA. so Hibernate specific answers dealing with hibernate specific API will not work for me.
I tried to look for hibernate configuration and see if I can set any configuration to stop this behavior but no luck.
Thanks
--EDIT ---
I couldn't find a solution to this, so I opted to rolling back the transaction without throwing any RuntimeException even though I'm in a declarative transaction using:
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
which works like a charm.
Configure FlushMode for your session.
http://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/FlushMode.html
You can use EntityManager.clear() method after getting object from database.
http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#clear()
You can call the following code:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
Throw an exception if validation fails and have the caller handle that.