2015-10-12 2 views
1

У меня есть база данных SQLite. Я работаю с ним с помощью EclipseLink и JPA. Кроме того у меня есть класс сущностей User:JPA EntityManager не вносит изменений в базу данных SQLite

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

В регистрационной форме я создаю пользователя и затем вызовите EntityManager на persist() изменения:

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

Он работает без каких-либо проблем. Я получаю каждого нового зарегистрированного пользователя в моей таблице USER. Однако, когда я пытаюсь сменить пароль, он не работает. Вот методы, связанные с этой процедурой:

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


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

Я также попытался с помощью EntityManager.find(...), который должен возвращать ту же строку из USER таблицы (и это делает), но результат опять же - начинается транзакция , заканчивается, диспетчер объектов закрывается, но таблица USER для якобы измененного пользователя - это то же самое.

Любые идеи? Я использовал ту же процедуру в другом проекте, но для установки других вещей. В базе данных был PostreSQL, и я не сталкивался с такими проблемами. Здесь, в базе данных SQLite, я не получаю ошибок, но коммит не работает.

+0

делает EclipseLink обеспечивает полную поддержку SQLite? Я знаю, что это не привыкло, и я использовал DataNucleus всякий раз, когда я хотел использовать этот хранилище данных. Глядя на журнал EclipseLink, скорее всего, вы увидите много –

+0

Я не вижу фиксации транзакции при запуске смены пароля. Кроме того, где я могу найти информацию о том, что поддерживает EclipseLink, когда дело доходит до SQLite. Я пробовал смотреть здесь и там, но ничего не получилось. Тем не менее, я действительно сомневаюсь, что он будет поддерживать 'persist()' (используя транзакцию!), Но не простое изменение значения в столбце. Я думаю, что ошибка находится где-то еще в коде, который я дал. Просто не знаю, где. Отладка не помогает вообще, так как я не получаю никакой ошибки. – rbaleksandar

+0

Хорошо, если я ищу «поддерживаемые Eclipselink базы данных», я получаю http://wiki.eclipse.org/EclipseLink/FAQ/JPA#What_databases_are_supported.3F –

ответ

1

Я просто разрабатываю спящий режим и т. Д., Но это будет то же самое, потому что оба реализуют JPA. Если вы начнете транзакцию, JPA запомнит все объекты, которые вы загрузите в этой транзакции, и если вы что-то измените, вы увидите изменения в db (после фиксации).

Но в вашей транзакции JPA не распознает вашу сущность, и поэтому изменения не будут сохраняться. Попробуйте загрузить объект в транзакции. Как ...

em.getTransaction().begin(); 
     em.find(User.class, currentUser.getId()); //Reload the User from db, so it is attached to the session 
     currentUser.setPassword(newPassword); 
    em.getTransaction().commit(); 

Дополнительная информация о методах:

+1

. Refresh выдает исключение, поскольку экземпляр не управляется. Его нужно объединить или прочитать. – Chris

+0

Было бы странно, если вы попытаетесь изменить пароль пользователя в базе данных не существует: P Но вы правы, обновление было бы проблемой, если объект не находится в базе данных. Также может возникнуть проблема, если вы обновите объект после его создания. Таким образом, в db не будет строки. В этом случае вам нужно использовать флеш. Для этого случая обновление или слияние было бы в порядке. Или вы можете сохранить объект после его модификации, это будет третий способ сделать то же самое. – Eruvanos

+0

Извините, я не имел в виду обновление - проблема, если строки там нет, я имел в виду, что это проблема, если экземпляр, который вы передаете, не управляется в текущем контексте. Refresh действителен только для экземпляров, управляемых этим EntityManager, поэтому сущность, прочитанная с любого другого em и передаваемая, вызовет исключение. Поскольку они закрывают контекст после чтения в currentUser и получают другое для обновления, я предлагал обновить ваше решение, чтобы использовать операцию поиска вместо обновления или использовать слияние. – Chris

Смежные вопросы