You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为EMF EObject声明时间戳属性,属性修改时自动赋值

解决方案:用EMF原生通知机制自动更新时间戳

嘿,这个需求完全可以靠EMF自带的属性变更通知体系来实现,不用搞序列化或者事务那套复杂的东西,直接在ReviewObject的实现类里加逻辑就行。下面给你一步步拆解:

1. 先确认模型里的lastModified属性配置正确

首先得保证你的.ecore模型里已经把lastModified定义成一个EDate类型的属性,这样生成的接口才会有你给出的setLastModified方法,同时对应的getter也得存在:

public interface ReviewObject extends EObject {
    /**
     * @generated
     */
    void setLastModified(Date value);
    
    /**
     * @generated
     */
    Date getLastModified();
}

2. 在实现类里监听属性变更,自动更新时间戳

EMF生成的实现类(比如ReviewObjectImpl)继承自EObjectImpl,有两个常用方法可以用来捕获属性变更:

方法一:重写eSet()(直接拦截setter调用)

所有EMF自动生成的setter最终都会调用eSet()来设置属性值,所以我们可以在这里做文章——先让父类完成属性设置,然后更新时间戳:

public class ReviewObjectImpl extends EObjectImpl implements ReviewObject {
    // ... 自动生成的其他代码 ...

    @Override
    public void eSet(int featureID, Object newValue) {
        // 先执行父类的属性设置逻辑
        super.eSet(featureID, newValue);
        
        // 拿到当前修改的属性,排除lastModified本身(避免无限循环)
        EFeature feature = eClass().getEStructuralFeature(featureID);
        if (feature instanceof EAttribute && feature != MyPackage.Literals.REVIEW_OBJECT__LAST_MODIFIED) {
            // 把时间戳设为当前时间
            setLastModified(new Date());
        }
    }
}

这里一定要排除lastModified属性,不然调用setLastModified时会再次触发eSet,陷入死循环。

方法二:重写eNotify()(覆盖所有变更场景)

如果你的模型里还有集合属性或者参考属性的修改(比如添加/移除关联对象),重写eNotify()会更全面,因为它能捕获所有EMF的变更通知:

public class ReviewObjectImpl extends EObjectImpl implements ReviewObject {
    // ... 自动生成的其他代码 ...

    @Override
    public void eNotify(Notification notification) {
        // 先处理原始的通知逻辑
        super.eNotify(notification);
        
        // 处理普通属性的SET事件
        if (notification.getEventType() == Notification.SET 
            && notification.getFeature() instanceof EAttribute
            && notification.getFeature() != MyPackage.Literals.REVIEW_OBJECT__LAST_MODIFIED) {
            setLastModified(new Date());
        }
        // 处理集合/参考属性的增删事件
        else if ((notification.getEventType() == Notification.ADD 
                  || notification.getEventType() == Notification.REMOVE
                  || notification.getEventType() == Notification.ADD_MANY
                  || notification.getEventType() == Notification.REMOVE_MANY)
                 && notification.getFeature() instanceof EReference) {
            setLastModified(new Date());
        }
    }
}

这个方法能覆盖几乎所有的对象变更场景,适合复杂一点的模型。

3. 几个要注意的点

  • 别搞死循环:一定要排除lastModified自身的变更,这个是重中之重。
  • 避免代码被覆盖:如果你的实现类是EMF自动生成的,直接改代码下次生成会被冲掉。最好是修改.genmodel里的模板配置,让生成的代码自动带上这段逻辑——找到ReviewObject的实现类设置,把自定义代码片段加到eSet或eNotify的生成模板里就行。
  • 线程安全(可选):如果是多线程环境,建议用System.currentTimeMillis()生成时间戳再转成Date,或者用AtomicLong来存储,避免并发问题。

内容的提问来源于stack exchange,提问作者Adam Horvath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:45:37