我想知道用户名是否已在使用中,如果不是,则电子邮件地址是否已在使用中。我不想为每个实体管理器查找方法开始并提交一个新事务,因为我认为仅使用一个事务进行多个操作比使用多个操作更有效。我可以在我的方法中用flush()替换commit()吗?
public void createUser(User_ newUser){
UserDao userDao = new UserDao();
Alert alert;
EntityTransaction transaction = entityManager.getTransaction();
try{
transaction.begin();
userDao.find("userName",newUser.getUserName());
transaction.commit();
alert = new Alert(Alert.AlertType.ERROR,"Username already in use", ButtonType.OK);
alert.showAndWait();
if (alert.getResult() == ButtonType.OK)alert.close();
}
catch(NoResultException e){
try{
transaction.begin();
userDao.find("emailAdress",newUser.getEmailAdress());
transaction.commit();
alert = new Alert(Alert.AlertType.ERROR,"E-mail adress already in use", ButtonType.OK);
alert.showAndWait();
if (alert.getResult() == ButtonType.OK) alert.close();
}
catch(NoResultException x){
transaction.begin();
userDao.save(newUser);
transaction.commit();
}
}
catch(RuntimeException e){
transaction.rollback();
}
finally{entityManager.close();}
}
谢谢。
最佳答案
您的代码存在三个问题:
为什么要将查询方法包装在单独的事务中?首先,执行查询不需要查询。其次,您尝试将两个查询方法包装在一个事务中是正确的,但原因是错误的。这与性能关系不大,而与隔离密切相关。这里需要一个事务,只是为了防止在这两个查询之间再次调用
createUser
创建具有相同用户名的用户(显然,出于同样的原因,持久化用户应该是同一事务的一部分) )。您应该避免使用异常来处理应用程序的正常状态。这不仅是使用异常的正确方法,而且就事务状态而言,您遇到的问题也会少得多。从您期望
userDao.find
抛出NoResultException
的事实来看,我假设它在内部使用query.getSingleResult()
。仅当您希望查询始终有结果时才应使用getSingleResult
。您应该使用getResultList()
来代替,并结合空性检查,或者更好的是,查询具有给定用户名的User
实体的 count您的方法混合了业务逻辑和表示问题。将数据保存到数据库并显示警报绝对不应该通过单一方法完成。如果您绝对需要以与保存数据相同的方法向用户传达错误,请确保在提交事务之后执行此操作,以防止超时。
关于java - 当我想使用find()方法两次时,我可以使用flush()而不是commit()吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44088452/