如何在 JSF 中自定义数据库唯一约束错误消息
How to customize database unique constraint error message in JSF
我有一个带有 UNI 约束的名称,当用户注册重复的名称时,它会抛出异常:
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'John' for key 'UK_t622yodh32su1s2wseebkimwp'
在JSF视图页面中,异常处理程序捕获的异常显示给用户:
Duplicate entry 'John' for key 'UK_t622yodh32su1s2wseebkimwp'
代码:
public void register (Student student) {
...
catch (Exception e) {
String errorMessage = getRootErrorMessage(e);
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Registration unsuccessful");
facesContext.addMessage(null, m);
}
}
private String getRootErrorMessage(Exception e) {
String errorMessage = "Registration failed.";
if (e == null) {
return errorMessage;
}
Throwable t = e;
while (t != null) {
errorMessage = t.getLocalizedMessage();
t = t.getCause();
}
return errorMessage;
}
Registration.xhtml:
<p>
<h:panelGrid columns="2">
<h:commandButton id="register"
action="#{registrationController.register(registrationView.student)}" value="Register"
styleClass="register" />
<h:messages styleClass="messages" errorClass="invalid"
infoClass="valid" warnClass="warning" globalOnly="true" />
</h:panelGrid>
</p>
这里的问题是,它只显示异常错误代码,如上。我想要类似这样的错误消息:
The user name has been registered, Please use another one. Thanks.
与 SQL 违反约束的错误消息相比,这对用户更友好。如何实现?
我认为添加消息与 jsf 生命周期有问题尝试创建一个 PhaseListener 以在面孔上下文中添加消息,如下所示:
public class FacesMessagesListener implements PhaseListener {
@Override
public void afterPhase(final PhaseEvent event) {
//add my messages to facesContext
}
@Override
public void beforePhase(final PhaseEvent event) {
//add my messages to facesContext
}
@Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}
我不太确定你所说的"exception error code"是什么意思?
在您的代码中,您明确地将 Java 异常消息放入 FacesMessage 中。如果您希望向用户显示不同的内容,则应该在 FacesMessage 中写入不同的内容。
但是,我建议您在尝试保留之前简单地检查用户是否已经存在。您应该通过这种简单的预检查来涵盖大多数情况:
public void register (Student student) {
if(service.exists(student)) {
String message = "The user name has been registered, Please use another one. Thanks.";
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, message,
"Registration unsuccessful");
facesContext.addMessage(null, m);
} else {
try {
service.create(student);
} catch (Exception e) {
String errorMessage = getRootErrorMessage(e);
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage,
"Registration unsuccessful");
facesContext.addMessage(null, m);
}
}
}
除此之外,您还可以在 SQLException 中显式检查是否存在完整性约束违规,但您无法通过这种方式区分不同类型的此类完整性约束违规。
public static boolean isConstraintViolation(SQLException e) {
return e.getSQLState().startsWith("23");
}
你也可以检查一下,报错信息中是否包含字符串Duplicate entry
,但不是很靠谱。
我更喜欢第一次建议的预检尝试。如果用户已经存在,则将适当的 FacesMassages 添加到 FacesContext。它将涵盖大多数情况。并且在极少数情况下,当两个用户同时注册相同的用户名时,向用户显示一个"Unexpected error"。
我有一个带有 UNI 约束的名称,当用户注册重复的名称时,它会抛出异常:
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'John' for key 'UK_t622yodh32su1s2wseebkimwp'
在JSF视图页面中,异常处理程序捕获的异常显示给用户:
Duplicate entry 'John' for key 'UK_t622yodh32su1s2wseebkimwp'
代码:
public void register (Student student) {
...
catch (Exception e) {
String errorMessage = getRootErrorMessage(e);
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Registration unsuccessful");
facesContext.addMessage(null, m);
}
}
private String getRootErrorMessage(Exception e) {
String errorMessage = "Registration failed.";
if (e == null) {
return errorMessage;
}
Throwable t = e;
while (t != null) {
errorMessage = t.getLocalizedMessage();
t = t.getCause();
}
return errorMessage;
}
Registration.xhtml:
<p>
<h:panelGrid columns="2">
<h:commandButton id="register"
action="#{registrationController.register(registrationView.student)}" value="Register"
styleClass="register" />
<h:messages styleClass="messages" errorClass="invalid"
infoClass="valid" warnClass="warning" globalOnly="true" />
</h:panelGrid>
</p>
这里的问题是,它只显示异常错误代码,如上。我想要类似这样的错误消息:
The user name has been registered, Please use another one. Thanks.
与 SQL 违反约束的错误消息相比,这对用户更友好。如何实现?
我认为添加消息与 jsf 生命周期有问题尝试创建一个 PhaseListener 以在面孔上下文中添加消息,如下所示:
public class FacesMessagesListener implements PhaseListener {
@Override
public void afterPhase(final PhaseEvent event) {
//add my messages to facesContext
}
@Override
public void beforePhase(final PhaseEvent event) {
//add my messages to facesContext
}
@Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}
我不太确定你所说的"exception error code"是什么意思?
在您的代码中,您明确地将 Java 异常消息放入 FacesMessage 中。如果您希望向用户显示不同的内容,则应该在 FacesMessage 中写入不同的内容。
但是,我建议您在尝试保留之前简单地检查用户是否已经存在。您应该通过这种简单的预检查来涵盖大多数情况:
public void register (Student student) {
if(service.exists(student)) {
String message = "The user name has been registered, Please use another one. Thanks.";
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, message,
"Registration unsuccessful");
facesContext.addMessage(null, m);
} else {
try {
service.create(student);
} catch (Exception e) {
String errorMessage = getRootErrorMessage(e);
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage,
"Registration unsuccessful");
facesContext.addMessage(null, m);
}
}
}
除此之外,您还可以在 SQLException 中显式检查是否存在完整性约束违规,但您无法通过这种方式区分不同类型的此类完整性约束违规。
public static boolean isConstraintViolation(SQLException e) {
return e.getSQLState().startsWith("23");
}
你也可以检查一下,报错信息中是否包含字符串Duplicate entry
,但不是很靠谱。
我更喜欢第一次建议的预检尝试。如果用户已经存在,则将适当的 FacesMassages 添加到 FacesContext。它将涵盖大多数情况。并且在极少数情况下,当两个用户同时注册相同的用户名时,向用户显示一个"Unexpected error"。