java.lang.IllegalStateException:事务已处于活动状态,事务处于非活动状态

时间:2016-08-19 14:54:39

标签: java mysql jpa javafx transactions

我有一个JavaFX应用程序,可以在JPA技术的帮助下访问MySQL数据库。

以下是我在应用程序中创建和使用实体管理器的方法:

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class EntityManagerHelper {

    private static final EntityManagerFactory emf;
    private static final ThreadLocal<EntityManager> threadLocal;

    static {
        if (InitPersistence.persistenceMap != null && InitPersistence.getNewIP() != null)
            emf = Persistence.createEntityManagerFactory("TonalityJPA",
                    InitPersistence.persistenceMap);
        else
            emf = Persistence.createEntityManagerFactory("TonalityJPA");
        threadLocal = new ThreadLocal<EntityManager>();
    }

    public static EntityManager getEntityManager() {
        EntityManager em = threadLocal.get();

        if (em == null) {
            em = emf.createEntityManager();
            // set your flush mode here
            threadLocal.set(em);
        }
        return em;
    }

    public static void closeEntityManager() {
        EntityManager em = threadLocal.get();
        if (em != null) {
            em.close();
            threadLocal.set(null);
        }
    }

    public static void closeEntityManagerFactory() {
        emf.close();
    }


    public static void begin() {
        getEntityManager().getTransaction().begin();
    }

    public static <T> void remove(T thingToRemove) {
        getEntityManager().remove(thingToRemove);
    }

    public static <T> void persist(T thingToPersist) {
        getEntityManager().persist(thingToPersist);
    }

    public static void rollback() {
        getEntityManager().getTransaction().rollback();
    }

    public static void commit() {
        getEntityManager().getTransaction().commit();

    }

    public static <T> T find(Class<T> a, long id) {
        return getEntityManager().find(a, id);
    }
}

我从这篇文章JAVA: an EntityManager object in a multithread environment的答案中选择了这个课程,并为其添加了一些功能。

我的应用程序通过DB进行授权,然后显示来自DB的用户列表。 应用程序用户选择其中一个并删除他。 这是如何运作的:

delBtn.setOnAction(event -> { 
                long id = currentUser.getUserId();
                new UserActions().delete(id);
                UserLogEntity userLog = new UserLogEntity(UserData.getUser().getUserId(), "deleted user: " +
                        currentUser.getUserLogin(), 3, new Date());
                UserLogActions log_action = new UserLogActions();
                log_action.add(userLog);
            } else {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("Помилка");
                alert.setHeaderText("");
                alert.setContentText("Оберіть користувача для видалення");

                alert.showAndWait();
            }

        });

以下是UserEntity和UserActions类:

UserEntity:

package com.Model.DataBase.Entities;

import org.mindrot.jbcrypt.BCrypt;

import javax.persistence.*;

/**
 * Created by User on 07.03.2016.
 */
@Entity
@Table(name = "user", schema = "newsmonitoringdb")
public class UserEntity {
    private Long userId;
    private String userLogin;
    private String userPass;
    private int userAccessLvl;

    public UserEntity(){}

    public UserEntity(String login, String pass, int accessLvl)
    {
        this.userLogin = login;
        this.userPass = pass;
        this.userAccessLvl = accessLvl;
    }    

    @Id
    @Column(name = "userID")
    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    @Basic
    @Column(name = "userLogin")
    public String getUserLogin() {
        return userLogin;
    }

    public void setUserLogin(String userLogin) {
        this.userLogin = userLogin;
    }

    @Basic
    @Column(name = "userPass")
    public String getUserPass() {
        return userPass;
    }

    public void setUserPass(String userPass) {
        this.userPass = userPass;
    }

    @Basic
    @Column(name = "userAccessLvl")
    public int getUserAccessLvl() {
        return userAccessLvl;
    }
}

UserAction:

package com.Model.DataBase.EntitiesActions;

import com.Model.DataBase.Entities.UserEntity;
import com.Model.DataBase.EntityManagerHelper;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;

public class UserActions{

    public List<UserEntity> list() {
        Query query = EntityManagerHelper.getEntityManager().createQuery("SELECT a FROM UserEntity a", UserEntity.class);
        return  (List <UserEntity>) query.getResultList();

    }

    public void add(UserEntity user) {
        try {
            EntityManagerHelper.begin();
            EntityManagerHelper.persist(user);
            EntityManagerHelper.commit();

        } catch (Exception ex) {
            //entityManager.getTransaction().rollback();
            //ex.printStackTrace();
        }
    }

    public void delete(long id) {
        try {
            UserEntity user = EntityManagerHelper.find(UserEntity.class, id);
            EntityManagerHelper.begin();
            EntityManagerHelper.remove(user);
            EntityManagerHelper.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            EntityManagerHelper.rollback();
        }
    }
}

如果我有

EntityManagerHelper.begin();

在delete方法中,我发送到此行的catch块,但有两个例外:

javax.persistence.RollbackException: Transaction marked as rollbackOnly

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Transaction not active

我理解第一个,但第二个意外。

如果我拿走这一行,我会从行中输入catch块:

EntityManagerHelper.commit();

第一个例外是相同的,第二个例外是 线程中的异常&#34; JavaFX应用程序线程&#34; java.lang.IllegalStateException:事务未激活

如何解决此问题以避免异常?

0 个答案:

没有答案