我有一个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
表返回同一行(它确实如此)但结果又一样 - 事务开始,结束,实体管理器关闭但是所谓改变的用户的表USER
是相同的。
有什么想法吗?我在另一个项目中使用了相同的例程但是用于设置其他项目。那里的数据库是PostreSQL,我还没有遇到过这样的问题。在这里使用SQLite数据库我没有错误,但提交以某种方式失败。
答案 0 :(得分:1)
我只是用hibernate等开发,但它会是相同的,因为它们都实现了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();
有关方法的更多信息: