简体   繁体   中英

javax.persistence.EntityManager not inserting things in database even when outside of the rollbacked transaction

I don't understand why my code acts a curtain way so it would be awesome if someone could explain. The problem I am facing... I have 2 tables. As soon the method starts I insert something in "table1", after the inserting I start the transaction. Let's assume that code flow will always reach transaction.rollback(). I expect for the second query to be rollbacked, but not the first one. But it seems to me that both of them are rollbacked.

TLDR;

Expected result:

  • First query is commited
  • Second query is rollbacked

Current outcome:

  • First query is rollbacked
  • Second query is rollbacked
//Relevant imports
import java.sql.PreparedStatement;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.jdbc.Work;

public boolean myMethod(String createdBy) {
        final Long messageId = ((BigInteger) myEntityManager.createNativeQuery("insert into table1(created_by) values (:createdBy) returning id")
                .setParameter("createdBy", createdBy)
                .getSingleResult()).longValue();

        Session session = myEntityManager.unwrap(Session.class);
        Transaction tx = session.beginTransaction();

        session.doWork(new Work() {
            @Override
            public void execute(Connection conn) throws SQLException {

                String sqlInsert = "insert into table2(messageId) values (?)";
                try ( PreparedStatement pstmt = conn.prepareStatement(sqlInsert)) {

                    for (Object[] row : unsentRecords) {
                        pstmt.setLong(1, messageId);
                        pstmt.addBatch();
                    }
                    //Execute batch
                    int[] sqlStatmentsStatuses = pstmt.executeBatch();
                    //check if some statement failed
                    //Let's assume it always fails,just to be explicit
                    boolean somethingWentWrong = atLeastOneFailed(sqlStatmentsStatuses);
                    somethingWentWrong = true;
                    if(somethingWentWrong){
                        tx.rollback();
                    }
                }
            }
        }
    }

NOTE: I don't know how to accurately call this question. So if someone can suggest a better title for the question put it in the comment and I will change it.

Below is Transaction#beginTransaction javadoc

Begin a unit of work and return the associated Transaction object. If a new underlying transaction is required, begin the transaction. Otherwise continue the new work in the context of the existing underlying transaction.

It says create begin new transaction if not available. In you case, you are already executing one query which is starting transaction. So when you say session.beginTransaction() , it's not creating new transaction but returning existing transaction and that's why when you do rollback on that transaction, both queries are getting rolled back.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM