我的应用程序中有一个表单,我正在尝试验证用户名和/或电子邮件是否已存在于数据库中。
这是服务类:
@Stateless
public class CustomerFacade extends AbstractFacade<Customer> {
@PersistenceContext(unitName = "OnlineStorePU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public CustomerFacade() {
super(Customer.class);
}
}
这是实体类:
@Entity
@Table(name = "customer")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Customer.findAll", query = "SELECT c FROM Customer c"),
@NamedQuery(name = "Customer.findById", query = "SELECT c FROM Customer c WHERE c.id = :id"),
@NamedQuery(name = "Customer.findByName", query = "SELECT c FROM Customer c WHERE c.name = :name"),
@NamedQuery(name = "Customer.findByMobile", query = "SELECT c FROM Customer c WHERE c.mobile = :mobile"),
@NamedQuery(name = "Customer.findByEmail", query = "SELECT c FROM Customer c WHERE c.email = :email"),
@NamedQuery(name = "Customer.findByAddress", query = "SELECT c FROM Customer c WHERE c.address = :address"),
@NamedQuery(name = "Customer.findByFax", query = "SELECT c FROM Customer c WHERE c.fax = :fax"),
@NamedQuery(name = "Customer.findByTelephone", query = "SELECT c FROM Customer c WHERE c.telephone = :telephone"),
@NamedQuery(name = "Customer.findByUsername", query = "SELECT c FROM Customer c WHERE c.username = :username")})
public class Customer implements Serializable {
//ALL GETTERS AND SETTERS + CONSTRUCTOR
}
这是检查表格的类:
public class ErrorUtils {
@EJB
private CustomerFacade customerFacade;
//**the arg String uName is the username input from the form**
private boolean isUserNameInDBOK(String uName) {
boolean OKBD = true;
// Checking UserName is not in the DB
for (Customer customer : customerFacade.findAll()) {
if (customer.getUsername().equals(uName)) {
OKBD = false;
break;
}
}
return OKBD;
}
}
我得到的错误是customerFacade
是null
:
Warning: StandardWrapperValve[ControllerServlet]: Servlet.service()
for servlet ControllerServlet threw exception java.lang.NullPointerException
这是如何引起的?如何解决?
答案 0 :(得分:1)
@EJB
注入仅适用于容器管理工件。即由容器本身创建的类的实例,因此不是由new
运算符创建的。
E.g。一个servlet:
@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {
@EJB
private YourService yourService;
}
容器单独执行new YourServlet()
。容器负责执行依赖注入。容器负责调用init()
。容器负责调用适当的doXxx()
方法。等等。它是一个容器管理的工件。
但是,您尝试将其注入某个实用程序类:
public class ErrorUtils {
@EJB
private CustomerFacade customerFacade;
}
这看起来不像容器管理的工件。鉴于类中完全没有任何与容器管理相关的注释,例如@Stateless
,@ApplicationScoped
,@WebServlet
等,您很可能只是自己手动创建它的实例如下所示:
ErrorUtils errorUtils = new ErrorUtils();
然后你期望@EJB
神奇地注入。
错误。
您使用ErrorUtils
关键字手动创建了new
类的实例。你是手动管理它。所以你基本上还需要手动抓取并设置那个EJB。通常,您使用JNDI,另请参阅Inject EJB bean from JSF managed bean programmatically。
errorUtils.customerFacade = (CustomerFacade) new InitialContext().lookup("java:/.../CustomerFacade");
但是,更好的是将该类转换为容器管理工件。例如。 CDI托管bean:
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class ErrorUtils {
然后将其注入您的servlet而不是手动制作它:
@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {
@Inject
private ErrorUtils errorUtils;
}
它会照顾@EJB
之类的所有依赖关系。
无关,下面没有意义:
private boolean isUserNameInDBOK(String uName) {
boolean OKBD = true;
// Checking UserName is not in the DB
for (Customer customer : customerFacade.findAll()) {
if (customer.getUsername().equals(uName)) {
OKBD = false;
break;
}
}
return OKBD;
}
你基本上是在破坏关系数据库系统的目的,低估了结构化查询语言SQL的能力。您基本上将整个数据库表完全复制到Java的内存中,然后在符合给定条件的情况下手动浏览每个记录。
这显然效率低下。您应该以这样的方式与数据库交互,使其返回完全您需要的信息,仅此而已。您可以使用WHERE
条款。您的IDE似乎足够聪明,可以为您自动生成这样的命名查询:Customer.findByName
。利用它。
private boolean isUserNameInDBOK(String uName) {
return customerFacade.findByName(name) != null;
}
这样DB将返回与给定条件匹配的1或0条记录。您只需检查它是否返回了记录。更高效的是添加一个命名查询,该查询会COUNT(*)
返回long
或boolean
而不是整个Customer
。即使这样,整个ErrorUtils
类在这个结构中也是多余的。只需直接调用服务方法。