使用Hibernate元数据构建表单校验功能

介绍了一种利用Hibernate元数据实现表单数据校验的方法,该方法可在业务层前置进行字段非空、数据类型及长度的有效性检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

表单数据的检验是应用程序必不可少的组成部分,通常来讲,表单数据的校验分为前台校验和后台校验两部分,前台校验使用JS脚本在提交数据前进行校验,后台校验在数据提交后进行校验。

      出于安全性的考虑,后台校验是必不可少的,当因为某种原因前台校验失效的情况下,由于有后台校验的存在,仍能保证提交数据的合法性和有效性。

      后台校验有许多种方法,有基于配置文件的校验,有基于注释的校验等等,也有许多成熟的校验框架可以使用。本文向大家介绍一种基于Hibernate元数据的校验方法,笔者曾在多个项目中使用,效果非常好,在这里与大家分享。

      应用本文提到的校验方法前应该满足以下几点:

 

  • 该程序持久层使用Hibernate。
  • 页面上的表单与数据库表有对应关系,且表单数据字段名与数据库字段名一致。
  • 最好使用了Spring。
      另外,使用基于Hibernate元数据的校验只能保证校验到字段是否为空、数据类型是否正确、字段长度是否符合三种规则。由于本文提到的方法是采用拦截器的方式在业务层前置进行校验,所以与其它的校验工具之间并不冲突,可以形成有效互补。
Java代码
  1. public class ValidationInterceptor extends HandlerInterceptorAdapter {  
  2.   
  3.     @Resource(name = "@sessionFactory")  
  4.     private LocalSessionFactoryBean sessionFactory;  
  5.   
  6.     @Override  
  7.     @SuppressWarnings("unchecked")  
  8.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
  9.         final String uri = request.getRequestURI();  
  10.         //通过请求的URI找到对应的校验实体类,这个需要在外部进行配置  
  11.         final String entityName = getValidation(uri);  
  12.         //没有配置说明这个请求不需要校验  
  13.         if (entityName == null)  
  14.             return true;  
  15.         //通过实体名返回Hibernate的PersistentClass  
  16.         final PersistentClass clazz = sessionFactory.getConfiguration().getClassMapping(entityName);  
  17.         //对应的表的元数据  
  18.         final Table table = clazz.getTable();  
  19.         final Iterator<Column> iterator = table.getColumnIterator();  
  20.         final Map<String, String> errors = new HashMap<String, String>();  
  21.         while (iterator.hasNext()) {  
  22.             //对应的列的元数据  
  23.             final Column column = iterator.next();  
  24.             //列名  
  25.             final String name = column.getName();  
  26.             //这是数据库列映射到JAVA中的属性  
  27.             final Property property = clazz.getProperty(name);  
  28.             //这是前台表单提交上来的值  
  29.             final String value = request.getParameter(name);  
  30.             //如果值为空,跳过该字段的校验  
  31.             if (value == null)  
  32.                 continue;  
  33.             //校验非空  
  34.             if (!column.isNullable() && "".equals(value.trim())) {  
  35.                 errors.put(name, "字段"+name+"的值不能为空!");  
  36.             }   
  37.             //校验字符串长度  
  38.             else if (property.getType() instanceof StringType) {  
  39.                 if (value.length() > column.getLength()) {  
  40.                     errors.put(name, "字段"+name+"的值超长了!");  
  41.                 }  
  42.             }   
  43.             //校验日期类型  
  44.             else if (property.getType() instanceof DateType) {  
  45.                 final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");  
  46.                 try {  
  47.                     format.parse(value);  
  48.                 } catch (Exception e){  
  49.                     errors.put(name, "字段"+name+"必须是日期类型!");  
  50.                 }  
  51.             }   
  52.             //校验数字类型,包括浮点数  
  53.             else if (property.getType() instanceof BigDecimalType) {  
  54.                 int precision = column.getPrecision();  
  55.                 int scale = column.getScale();  
  56.                 int front = precision - scale;  
  57.                 String patten = "";  
  58.                 for (int i = 0; i < front; i++) {  
  59.                     patten += "#";  
  60.                 }  
  61.                 if (scale > 0) {  
  62.                     patten += ".";  
  63.                     for (int i = 0; i < scale; i++) {  
  64.                         patten += "#";  
  65.                     }  
  66.                 }  
  67.                 final NumberFormat format = new DecimalFormat(patten);  
  68.                 try {  
  69.                     format.parse(value);  
  70.                 } catch (Exception e) {  
  71.                     errors.put(name, "字段"+name+"必须是数字类型("+patten"+")!");  
  72.                 }  
  73.             }  
  74.         }  
  75.         //如果没有错误,直接放行  
  76.         if (errors.isEmpty())  
  77.             return true;  
  78.         //有错了,生成描述错误信息的JSON串,返回前台  
  79.         response.setContentType("text/json;charset=UTF-8");  
  80.         response.getWriter().write(JSONObject.fromObject(errors).toString());  
  81.         response.getWriter().close();  
  82.         return false;  
  83.     }  
  84. }  
      每个URL需要映射一下校验数据使用的实体类,可以使用一个Propertes文件进行配置,上代码中的getValidation方法需要从这个配置文件中取信息。
Java代码
  1. /test/save_log.do=com.coolfancy.blog.entity.Log  
  2. /test/save_reply.do=com.coolfancy.blog.entity.Reply  
      使用这个方法后,基于数据库元数据的校验就不需要再在程序中写了,使用这个拦截器就全搞定了,如果有其它复杂的校验,可以在Action中使用原来的校验方法继续校验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值