codecamp

过滤字段

为什么需要过滤字段

某些时候,尤其是在更新对象的时候,用户希望忽略某些字段。 通过注解 Nutz.Dao 实体注解 @Readonly 可以达到 这个目的。但是更多的时候, 对于 POJO 对象,只有在运行时,用户的程序才能决定哪些字段更新,哪些不更新。@Readonly 注解可就达不到这个 目的了。

怎么办呢? Nutz.Dao 提供了类似于 动态表名 的解决办法。

如何过滤字段的例子

如下代码,将只更新 Pet 的 id 和 name 字段:

FieldFilter.create(Pet.class, "^id|name$").run(new Atom() {
    public void run() {
        Pet pet = dao.fetch(Pet.class, 24);
        pet.setName("ABC");
        pet.setNickname("XiaoBai");
        dao.update(pet);
    }
});

字段过滤器的原理

字段过滤,不过是要在一个地方记录一下下面两个信息:

  1. 对什么实体
  2. 过滤哪些字段

并且它希望 Nutz.Dao 自行能获取到这些信息。当然,ThreadLocal 就是一个很好的选择。实际上,你如果 看看 FieldFilter 里面的方法,你其实就能猜到。为了能为多个实体保存字段过滤配置信息,它实际上在 ThreadLoacal 里保存了自身的一个实例,同时,它自己有一个私有的 Map<Class<?>, FieldMatcher>, 具体的,你可以看 FieldFilter 这个类的定义:

public class FieldFilter {

    ...
    private static ThreadLocal<FieldFilter> FF = new ThreadLocal<FieldFilter>();
    ...
    private Map<Class<?>, FieldMatcher> map;
    ...

而且既然在 ThreadLocal 设置了数据,它就不得不考虑 如何让你清除这个数据。因此,它的写法也保证了你一定会清掉你的数据了。

FieldFilter ... run(new Atom(){   <-- 开始将自身加入 ThreadLocal
    public void run(){
        // 这里是你的代码,你的 Dao 调用都会得到 ThreadLocal 中你对于实体字段过滤的设置
    }
});   <-- run 方法结束前,会从 ThreadLocal 清除自身

字段过滤器的创建

下面是一个最简单和常用的例子:

FieldFilter.create(Pet.class, "^id|name$").run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});
  • 这样,无论你查询或者更新等操作,对 Pet 这个实体只会针对能被正则表达式 "id|name" 匹配的字段进行操作
    • 实际上,上例的正则表达式表示: 所有包括 id 和 name 字符的字段
  • 如果你想仅仅让 id 和 name 字段受到匹配,你的正则表达式最好写的严格一些,比如 "^id|name$"
  • 当然,SQL 的条件部分不会受到字段过滤器的影响

如果你读完上面的介绍,你应该就很了解字段过滤器如何使用了,但是你可能还有个几个小疑问:

  • 如果我字段比较多怎么办呢?
  • 如果我想忽略所有之为空的字段怎么办呢?
  • 如果我想同时为多个实体设置字段过滤怎么办呢?

忽略少数字段

FieldFilter.locked(Pet.class, "^last|age$").run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});

忽略空值

FieldFilter.create(Pet.class, true).run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});

保留几个字段且忽略空值

FieldFilter.create(Pet.class,"^id|name|age|last$", true).run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});

忽略少数字段且忽略空值

FieldFilter.create(Pet.class, null, "^age|last$", true).run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});

为多个实体设置字段过滤

FieldFilter.create(Pet.class, true)
           .set(Master.class, "^id|name$")
           .run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});

无需匿名内部类的写法

从1.b.51开始支持不使用匿名内部类的方法, Daos.ext方法. 该方法有两个变种, 分别支持字段过滤和动态表名.

示例

//原写法
FieldFilter.create(Pet.class, "^id|name$").run(new Atom(){
    public void run(){
        dao.update(pet); // 这里的pet必须是final
    }
});
// 新的写法
Daos.ext(dao, FieldFilter.create(Pet.class, "^id|name$")).update(pet);
// ext方法会返回一个Dao实例,是对原有dao对象的封装
使用视图
动态表名
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

表达式引擎

maplist结构

图像处理小军刀

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }