In our previous post we saw how to transition a detached object back to a persistent state. Is it possible to delete an entity from the database if it is not associated with any session? Would Hibernate throw an exception or would the delete succeed? Or would the code simply crash ? The best way to be sure is to try it out on our own :
On closing the session, the persistent object is now detached. We then open a new session and attempt to delete the transient object without re-attaching it to the session.
Thus to delete objects, there is no need to manually reattach them to the session.public static void deleteTransient() { Session session1 = sessionFactory.openSession(); Entity entity = new Entity(); entity.setData("Temp Object"); Transaction transaction = session1.beginTransaction(); final Integer id = (Integer) session1.save(entity); System.out.println("The id is " + id); // Object will be now be saved to the db transaction.commit(); session1.close(); //The object is now detached Session session2 = sessionFactory.openSession(); transaction = session2.beginTransaction(); session2.delete(entity); //The object is now removed transaction.commit(); session2.close(); System.out.println("The id is " + entity.getId()); }Here we have created an object that is initially in the transient state. We then saved it to the database moving it to a persistent state.
On closing the session, the persistent object is now detached. We then open a new session and attempt to delete the transient object without re-attaching it to the session.
2407 [main] DEBUG org.hibernate.SQL - insert into Entity (DATA) values (?) The id is 9 ... 2469 [main] DEBUG org.hibernate.impl.SessionImpl - after transaction completion 2469 [main] DEBUG org.hibernate.impl.SessionImpl - closing session ... 2532 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Dele ting entity: [com.model.Entity#9] 2532 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedSt atement (open PreparedStatements: 0, globally: 0) 2532 [main] DEBUG org.hibernate.SQL - delete from Entity where id=? 2578 [main] DEBUG org.hibernate.impl.SessionImpl - after transaction completion 2578 [main] DEBUG org.hibernate.impl.SessionImpl - closing session The id is nullAs can be seen the object was created successfully in the first session and then also deleted successfully in session number two.Thus the delete method takes care of two steps:
- It reattaches the detached object to the session.
- It then schedules the object for deletion.
Would this code work ?
public static void deleteUnloaded() { Session session1 = sessionFactory.openSession(); Entity entity = new Entity(); entity.setData("Temp Object"); Transaction transaction = session1.beginTransaction(); session1.delete(entity); transaction.commit(); session1.close(); }I took a new object and tried to delete it. The logs are as follows:
2265 [main] DEBUG org.hibernate.jdbc.JDBCContext - after transaction begin 2281 [main] DEBUG org.hibernate.event.def.DefaultDeleteEventListener - entity w as not persistent in delete processing 2297 [main] INFO org.hibernate.event.def.DefaultDeleteEventListener - handling transient entity in delete processing 2297 [main] DEBUG org.hibernate.impl.SessionImpl - automatically flushing sessi on 2297 [main] DEBUG org.hibernate.jdbc.JDBCContext - before transaction completio n 2297 [main] DEBUG org.hibernate.impl.SessionImpl - before transaction completio n 2297 [main] DEBUG org.hibernate.transaction.JDBCTransaction - committed JDBC Co nnection 2297 [main] DEBUG org.hibernate.jdbc.JDBCContext - after transaction completionAs can be seen no delete query was fired. I then tweaked the code.
Entity entity = new Entity(); entity.setId(2); //entity.setData("Temp Object");Earlier the id field was null and so Hibernate was unable to perform the delete. Here I set the right id and executed the code:
781 [main] DEBUG org.hibernate.event.def.DefaultDeleteEventListener - entity was not persistent in delete processing 814 [main] DEBUG org.hibernate.event.def.AbstractFlushingEventListener - Flush ed: 0 insertions, 0 updates, 1 deletions to 1 objects 818 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Dele ting entity: [com.model.Entity#2] delete from ENTITY where id=?As seen above Hibernate treated the new object like a transient object and scheduled it for deletion aftre re-attaching it to a session.
public static void deleteProxy() { Session session1 = sessionFactory.openSession(); Entity entity = (Entity) session1.load(Entity.class, 2); Transaction transaction = session1.beginTransaction(); session1.delete(entity); transaction.commit(); session1.close(); }The logs now showed a different result:
2282 [main] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13537451031 2313 [main] DEBUG org.hibernate.event.def.DefaultLoadEventListener - loading en tity: [com.model.Entity#2] 2313 [main] DEBUG org.hibernate.event.def.DefaultLoadEventListener - creating n ew proxy for entity ... 2329 [main] DEBUG org.hibernate.jdbc.JDBCContext - after transaction begin 2329 [main] DEBUG org.hibernate.impl.SessionImpl - initializing proxy: [com.mod el.Entity#2] ... 2329 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Fetc hing entity: [com.model.Entity#2] 2344 [main] DEBUG org.hibernate.SQL - select entity0_.id as id0_0_, entity0_.DATA as DATA0_0_ from Entity entity0_ where entity0_.id=? 2391 [main] DEBUG org.hibernate.loader.Loader - done entity load ... 2391 [main] DEBUG org.hibernate.event.def.DefaultDeleteEventListener - deleting a persistent instance 2391 [main] DEBUG org.hibernate.event.def.DefaultDeleteEventListener - deleting [com.model.Entity#2] 2422 [main] DEBUG org.hibernate.SQL - delete from Entity where id=?As can be seen both a delete and a select query was fired. But I was working with a proxy. So why the select query ?
This is important: An object can be deleted only if it exists in the session's persistence context. When we made the delete call, Hibernate did not find the object in the persistence context (Remember proxies will not be there in it.) So Hibernate had to first fetch the object and then delete it.
No comments:
Post a Comment