如何为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
相关产品推荐
相关产品推荐

