lundi 12 octobre 2015

JPA EntityManager doesn't commit changes in SQLite database

I have an SQLite database. I work with it using EclipseLink and JPA. In addition I have an entity class User:

import com.vaadin.server.VaadinService;
import java.io.Serializable;
import javax.persistence.*;

@Entity
public class User implements Serializable {

    @Id @GeneratedValue
    long id;            // Unique identifier of the user in the DB
    String username;    // Unique name used for login
    String password;    // Password used for login

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public Long getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

In a registration form I create a user and then call an EntityManager to persist() the changes:

public int createUser(String username, String password, String password_confirmation) {
        int regStatus = 0;
        if(checkValidUsername(username)) {
            if(checkValidPassword(password, password_confirmation)) {
                EntityManager em = factory.createEntityManager();
                try {
                    em.getTransaction().begin();
                        User user = new User(username, password);
                        em.persist(user);
                    em.getTransaction().commit();
                }
                catch(Exception e) {
                    System.out.println(e.getMessage());
                    regStatus = 3;
                }
                finally {
                    em.close();
                }
            }
            else regStatus = 2; // Password mismatch
        }
        else regStatus = 1;     // User with selected username already present in DB

        return regStatus;
    }

It works without any problems. I get each and every newly registered user in my USER table. However when I try to change the password it doesn't work. Here are the methods that are related to this procedure:

// Inside the controller for my settings view - here the user can change various things related to his/her profile
public void setCurrentUser() {
    currentUser = controller.findUserByName((String)VaadinSession.getCurrent().getAttribute("username"));
}


// Inside the User controller I have multiple methods for common user-related queries; here I use the username that I have retrieved from the VaadinSession's attribute "username" to execute a query and get the User entity (I make sure that a user's name is unique so getting a single result here is not a problem)
public static User findUserByName(String username) {
    if(username == null) return null;
    factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    EntityManager em = factory.createEntityManager();
    User user = null;

    try{
        Query q = em.createQuery("SELECT u FROM User u WHERE u.username = :username");
        q.setParameter("username", username);
        user = (User)q.getSingleResult();

    }
    catch(Exception e){
        System.err.println(e.getMessage());
    }
    finally {
        em.close();
    }

    return user;
}


// Inside the controller fpr my settings view (where I change the password)
public int changePassword(String currentPassword, String newPassword, String newPasswordConfirmation) {
    if(newPassword.isEmpty()) return 1;
    if(!newPassword.equals(newPasswordConfirmation)) return 2;          // Incorrect confirmation
    if(!currentPassword.equals(currentUser.getPassword())) return 3;    // Given current password doesn't match the one stored in the database for this user

    int resStatus = 0;
    EntityManager em  = factory.createEntityManager();
    try {
        em.getTransaction().begin();
            currentUser.setPassword(newPassword);
        em.getTransaction().commit(); // NO ERRORS at all...
    }
    catch(Exception e) {
        System.out.println(e.getMessage());
        resStatus = 4;  // Exception
    }
    finally {
      em.close();
    }

    return resStatus;
}

I have also tried using EntityManager.find(...), which should return the same row from the USER table (and it does) but the result is again the same - transaction begins, finishes, entity manager closes but the table USER for the supposedly changed user is the same.

Any ideas? I have used the same routine in another project but for setting other things. The database there was PostreSQL and I haven't encountered such issues. Here with the SQLite database I get no errors but the commit fails somehow.

Aucun commentaire:

Enregistrer un commentaire