设为首页 收藏本站
查看: 1382|回复: 0

[Cloudstack] CloudStack的VO在调用setRemoved方法抛异常的原因

[复制链接]

尚未签到

发表于 2015-4-18 09:22:27 | 显示全部楼层 |阅读模式
  今天在开发中发现一个问题,本来想对一个VO对象的removed值赋值,然后去update一下这条记录,一个最简单的set方法,但是在调用时直接抛异常了。

  1: public void setRemoved(Date removed) {

  2:     this.removed = removed;

  3: }
  当时很诧异,没有想到这地方会出问题,后来看代码才发现原来cs在这里有拦截器,com.cloud.utils.db.UpdateBuilder#intercept

  1: @Override

  2: public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

  3:     String name = method.getName();

  4:     if (name.startsWith("set")) {

  5:         String field = methodToField(name, 3);

  6:         makeChange(field, args[0]);

  7:     } else if (name.startsWith("incr")) {

  8:         makeIncrChange(name, args);

  9:     } else if (name.startsWith("decr")) {

10:         makeDecrChange(name, args);

11:     }

12:     return methodProxy.invokeSuper(object, args);

13: }
  所有set开头的方法都被拦截,转调com.cloud.utils.db.UpdateBuilder#makeChange

  1: protected Attribute makeChange(String field, Object value) {

  2:     Attribute attr = _dao._allAttributes.get(field);

  3:

  4:     assert (attr == null || attr.isUpdatable()) : "Updating an attribute that's not updatable: " + field;

  5:     if (attr != null) {

  6:         if (attr.attache == null) {

  7:             _changes.put(field, new Ternary(attr, null, value));

  8:         } else {

  9:             if (_collectionChanges == null) {

10:                 _collectionChanges = new HashMap();

11:             }

12:             _collectionChanges.put(attr, value);

13:         }

14:     }

15:     return attr;

16: }
  
  在那句assert那里,会判断attr是否可以update。
  Attribute是cloudstack的基类GenericDaoBase中保存的对象属性集合,是一个保存了数据表的列名以及列属性的Map对象,这个对象通过Java JPA来进行持久化。
  每一个干活的DAO对象都会继承于GenericDaoBase,并且实现自己这类对象的接口,如下图:
DSC0000.png
  
  刚才说的那个isUpdatable()是个人认为cloudstack中有关数据库权限做的很精巧的地方

  1: public final boolean isUpdatable() {

  2:     return Flag.Updatable.check(flags);

  3: }
  
  这里面会调用Flag这个enum对象的check方法,那个flags同样也是在调用Attribute的构造方法时生成的,它根据数据库表的每一列的属性,按照一个逻辑去计算相关的权限,flags的初始值为0,然后针对每一种权限依次去做或运算,最后保存为一个值,遇到需要校验权限的地方,就用下面的check方法,看传进来的权限,比如Flag.Updatable,与flags去与运算,如果与完了的结果与传进来的权限值一样,那么可以继续进行,否则就会由于assert计算表达式的结果为false而退出去。

  1: public boolean check(int value) {

  2:     return (value & place) == place;

  3: }

  今天的问题就在这,Attribute.flags的值导致assert的表达式结果为false,在初始化时,flags的值明明为135(128+4+2+1),但是在实际计算时却不是这个值,一度很不解。但是为了解决生产环境的问题,不能在这个细节上耽搁太久,于是换了个思路,尝试着调用DAO的remove方法,也能实现针对数据库表的removed字段赋值。具体到为什么flags的值变了,还需要抽时间好好研究一下。
  不过值得欣慰的是,如果不是set时抛异常了,自己可能也不会去啃这部分代码来了解。
  附1,计算flags时的代码(com.cloud.utils.db.Attribute#setupColumnInfo):

  1: protected void setupColumnInfo(Class clazz, AttributeOverride[] overrides, String tableName, boolean isEmbedded, boolean isId) {

  2:     flags = Flag.Selectable.setTrue(flags);

  3:     GeneratedValue gv = field.getAnnotation(GeneratedValue.class);

  4:     if (gv != null) {

  5:         if (gv.strategy() == GenerationType.IDENTITY) {

  6:             flags = Flag.DbGenerated.setTrue(flags);

  7:         } else if (gv.strategy() == GenerationType.SEQUENCE) {

  8:             assert (false) : "Sequence generation not supported.";

  9:             flags = Flag.DaoGenerated.setTrue(flags);

10:             flags = Flag.Insertable.setTrue(flags);

11:             flags = Flag.SequenceGV.setTrue(flags);

12:         } else if (gv.strategy() == GenerationType.TABLE) {

13:             flags = Flag.DaoGenerated.setTrue(flags);

14:             flags = Flag.Insertable.setTrue(flags);

15:             flags = Flag.TableGV.setTrue(flags);

16:         } else if (gv.strategy() == GenerationType.AUTO) {

17:             flags = Flag.DaoGenerated.setTrue(flags);

18:             flags = Flag.Insertable.setTrue(flags);

19:             flags = Flag.AutoGV.setTrue(flags);

20:         }

21:     }

22:

23:     if (isEmbedded) {

24:         flags = Flag.Embedded.setTrue(flags);

25:     }

26:

27:     if (isId) {

28:         flags = Flag.Id.setTrue(flags);

29:     } else {

30:         Id id = field.getAnnotation(Id.class);

31:         if (id != null) {

32:             flags = Flag.Id.setTrue(flags);

33:         }

34:     }

35:     column = field.getAnnotation(Column.class);

36:     if (gv == null) {

37:         if (column == null || (column.insertable() && column.table().length() == 0)) {

38:             flags = Flag.Insertable.setTrue(flags);

39:         }

40:         if (column == null || (column.updatable() && column.table().length() == 0)) {

41:             flags = Flag.Updatable.setTrue(flags);

42:         }

43:         if (column == null || column.nullable()) {

44:             flags = Flag.Nullable.setTrue(flags);

45:         }

46:         Encrypt encrypt = field.getAnnotation(Encrypt.class);

47:         if (encrypt != null && encrypt.encrypt()) {

48:             flags = Flag.Encrypted.setTrue(flags);

49:         }

50:     }

51:     ElementCollection ec = field.getAnnotation(ElementCollection.class);

52:     if (ec != null) {

53:         flags = Flag.Insertable.setFalse(flags);

54:         flags = Flag.Selectable.setFalse(flags);

55:     }

56:

57:     Temporal temporal = field.getAnnotation(Temporal.class);

58:     if (temporal != null) {

59:         if (temporal.value() == TemporalType.DATE) {

60:             flags = Flag.Date.setTrue(flags);

61:         } else if (temporal.value() == TemporalType.TIME) {

62:             flags = Flag.Time.setTrue(flags);

63:         } else if (temporal.value() == TemporalType.TIMESTAMP) {

64:             flags = Flag.TimeStamp.setTrue(flags);

65:         }

66:     }

67:

68:     if (column != null && column.table().length() > 0) {

69:         table = column.table();

70:     }

71:

72:     columnName = DbUtil.getColumnName(field, overrides);

73: }
  
  附2,数据库表每一列可能的所有权限列表:
DSC0001.png

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58334-1-1.html 上篇帖子: CLOUDSTACK我也来啦 下篇帖子: CloudStack 物理网络架构
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表