views:

367

answers:

1

Hi every one, I want update some of my table in database and want all of these work do in 1 transaction, first of all I delete some entry in branchbuildin(Table) and Insert new one after this action The problem occurred when I insert and entry with same buildingname and branch_fk (be cause I have this constraint on this table ( uniqueConstraints={@UniqueConstraint(columnNames={"buildingname","branch_fk"})})) but when I don't use hibernate session and use normal JDBC transaction I don't have these problem.

List<Integer> allBranchBuilding = branchBuildingDao.getAllBranchBuildingID(pkId, sess);
            for (Integer integer : allBranchBuilding) {
                branchBuildingDao.delete(integer, sess); // delete kardane tamame BranchBuilding ha va tel haie aanha
            }

            Address myAdr = new Address();
            setAddress(myAdr, centralFlag, city, latit, longit, mainstreet, remainAdr, state);
            BranchBuildingEntity bbe = new BranchBuildingEntity();
            setBranchBuildingEntity(bbe, be, myAdr, city, centralFlag, latit, longit, mainstreet, buildingName, remainAdr, state, des);
            branchBuildingDao.save(bbe, sess);//Exception Occurred

I get my session at the first of Method:

        Session sess = null;
        sess = HibernateUtil.getSession();
        Transaction tx = sess.beginTransaction();
+2  A: 

You're right, everything occurs in the same transaction, and the same Hibernate Session.

The Session keeps track of every entity it manages. Even though you asked to delete it in the database, the corresponding object is still memorised in the Session until the Session is terminated.

In general, it is possible that Hibernate reorders your operations when sending them to the database, for efficiency reasons.

What you could do is flush (ie. send to the database) your transaction because the save (if needed, you could also clear - ie empty the entities memorized by the Session - it after flushing):

sess.flush();
// sess.clear(); // if needed or convenient for you
branchBuildingDao.save(bbe, sess);

Note also that while your entities are memorized by the session, modifying them will trigger an automatic update when closing the session.

In our project, we have a method that deletes efficiently a collection (and another for an array, declared using the convenient ... parameter syntax) of entities (it works for all entities, it doesn't have to be done for each entity), removing them out of the session at the same time, and taking care of the flushing before :

  1. Loop on all entities, delete it (using sess.delete(e)) and add it to a 'deleteds' list.
  2. Every 50 entities (corresponding to the batch size we configured for efficiency reasons) (and at the end) :
    • flush the Session to force Hibernate to send immediately the changes to the database,
    • loop on 'deleteds' list, clear each entity from the Session (using sess.evict(e)).
    • empty the 'deleteds'list.

Don't worry, flush only sends the SQL to the database. It is still subject to commit or rollback.

KLE
Tanx but what happen if I flus the session and after that my connection CUTOFF does the transaction rollback after flush?I need all of my job done in one transaction(can i use flush between them and dun hurt transaction rollback and commit?)
Am1rr3zA
KLE is right (except for invoking `evict()` on previously deleted entity which is very questionable, but not pertinent to issue at hand) "flush" is just a process for synchronizing session state with the database, e.g. it will issue the necessary insert / update / delete statements to the database. With regards to transaction that's no different from manually issuing the very same statements - unless transaction is committed, all those statements will be rolled back (because of explicit rollback, terminated connection, server dying, what have you).
ChssPly76
@ChssPly76 Hi. I'm curious about your "evict" comment. Could you expand on the issue ?
KLE
Under the best circumstances (instance being deleted is not referenced elsewhere in the application) subsequent eviction is pretty pointless (if you're doing it to save memory you're either holding on to your session for too long OR you should be using bulk delete HQL). If the entity _is_ referenced from somewhere, you're cheating yourself out of fail-fast "deleted entity passed to persist" exception by evicting it. Yes, that would only happen if your code has a bug, but something like this is _VERY_ hard to catch. That's where all the "help! my deleted records are reappearing" bugs come from
ChssPly76