2

I have got a JavaFX application, which gets access to MySQL database with the help of JPA technology.

Here is how I create and use entity manager in my application:

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);
    }
}

I took this class from the answer to this post JAVA: an EntityManager object in a multithread environment and added some functions to it.

My application goes through authorization through DB, then shows the list of users from DB. Application user chooses one of them and deletes him. Here how it works:

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();
            }

        });

And here are the UserEntity and UserActions classes:

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();
        }
    }
}

In case if I have

EntityManagerHelper.begin();

in delete method, I am send to the catch block at this line with two exceptions:

javax.persistence.RollbackException: Transaction marked as rollbackOnly

and

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

I understand the first one, but the second one is unexpected.

if I take away this line, I enter the catch block from the line:

EntityManagerHelper.commit();

The first exception is the same, the second exception is Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Transaction not active

How can I solve this issue to get no exceptions?

Community
  • 1
  • 1
Andrey
  • 45
  • 1
  • 6

0 Answers0