【问题标题】:javax.persistence.EntityManager not inserting things in database even when outside of the rollbacked transaction即使在回滚事务之外,javax.persistence.EntityManager 也不会在数据库中插入东西
【发布时间】:2022-07-06 23:09:41
【问题描述】:

我不明白为什么我的代码会起到幕后的作用,所以如果有人能解释一下就太好了。我面临的问题...我有 2 张桌子。一旦方法开始,我在“table1”中插入一些东西,插入之后我开始事务。假设代码流总是会到达 transaction.rollback()。我希望第二个查询被回滚,但不是第一个。但在我看来,它们都被回滚了。

TLDR;

预期结果:

  • 第一个查询已提交
  • 第二个查询被回滚

目前的结果:

  • 第一个查询已回滚
  • 第二个查询被回滚
//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();
                    }
                }
            }
        }
    }

注意:我不知道如何准确地称呼这个问题。因此,如果有人可以为问题提出更好的标题,请将其放在评论中,我会更改它。

【问题讨论】:

  • 你检查过messageId的值吗?通常,您只能在事务之外检索数据。要持久化或更新数据,您需要一个活动事务

标签: java hibernate jpa


【解决方案1】:

下面是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.

它说如果不可用,则创建开始新事务。在您的情况下,您已经在执行一个正在启动事务的查询。因此,当您说session.beginTransaction() 时,它不是创建新事务,而是返回现有事务,这就是为什么当您对该事务进行回滚时,两个查询都会回滚。

【讨论】:

    猜你喜欢
    • 2015-03-12
    • 2012-07-23
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-08
    • 1970-01-01
    相关资源
    最近更新 更多