【发布时间】:2016-01-10 07:53:07
【问题描述】:
我有一个 SQLite 数据库。我使用 EclipseLink 和 JPA 来处理它。另外我还有一个实体类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;
}
}
在注册表单中,我创建了一个用户,然后调用 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 表中返回同一行(确实如此),但结果还是一样——事务开始、完成、实体管理器关闭但表@987654331 @ 被假定更改的用户是相同的。
有什么想法吗?我在另一个项目中使用了相同的例程,但用于设置其他内容。那里的数据库是PostreSQL,我还没有遇到过这样的问题。在使用 SQLite 数据库时,我没有收到任何错误,但提交以某种方式失败。
【问题讨论】:
-
Eclipselink 是否提供对 SQLite 的全面支持?我知道它不习惯,而且每当我想使用该数据存储时,我都会使用 DataNucleus。查看 EclipseLink 日志可能会发现很多
-
触发更改密码时,没有看到任何事务提交。另外,我在哪里可以找到一些关于 EclipseLink 在 SQLite 方面支持的信息。我试着四处寻找,但什么也没出现。仍然我真的怀疑它是否支持
persist()(使用事务!)但不是简单地更改列中的值。我认为错误在我给出的代码中的其他地方。就是不知道在哪里。调试根本没有帮助,因为我没有收到任何错误。 -
如果我搜索“Eclipselink 支持的数据库”,我会得到wiki.eclipse.org/EclipseLink/FAQ/…
-
并查看当您想要更新其字段时“currentUser”处于什么状态。管理好了吗?分离?
-
它将被分离,因为他使用 factory.createEntityManager() 获得了一个新的 EntityManager 用于事务。用户需要使用该 EntityManager 进行合并或读入
标签: sqlite jpa transactions eclipselink entitymanager