该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-11-15
2.9.5 自定义数据库映射 正如在2.9.2节所说的,如果你喜欢用setXXX或getXXX这样的风格来访问属性值, 你可以自己编写一个实现com.douyu.sql.DatabaseMapping接口的类, 或者更简单的,直接继承com.douyu.sql.DefaultDatabaseMapping类, 然后像下面这样覆盖getPropertySetterGetterStyle()方法(默认是STYLE_DEFAULT), public int getPropertySetterGetterStyle() { return STYLE_SET_GET_PREFIX; } 如果你想完全自定义,那么把STYLE_SET_GET_PREFIX改成STYLE_CUSTOM, 并且实现或覆盖下面两个方法: String columnName2setterName(String tableName, String columnName); String columnName2getterName(String tableName, String columnName); Douyu通过com.douyu.sql.DatabaseMapping接口给开发人员打开了一扇门, 使得开发人员可以对Douyu的ORM进行少量的控制, DatabaseMapping接口除了上面给出的三个方法外,还有如下方法: String tableName2className(String tableName); String columnName2propertyName(String tableName, String columnName); String getSequenceName(String tableName, String columnName); String getSQLEventListener(String tableName); String getPropertyListener(String tableName, String columnName); 所有的tableName、columnName参数都是小写的, 如果数据库表中有一个表名所包含的字符是Java语言中不允许的(如表名含#号), 那么你可以通过tableName2className来转换,返回的类名是不含包名的, 通常的做法是写个Map<String,String>,在初始化时把表名和类名放进去。 columnName2propertyName方法也类似, 有些表的列名是不能出现在Java语言中的,如一个叫"default"的列就是非法的, 在初始化时,你也可以用一个两级Map来实现,第一级是表名,第二级是列名。 默认情况下columnName2propertyName方法返回的属性名总是跟列名一样的, 所有的Setter、Getter都是由这个返回的属性名来生成的, 如果把模型类作为控制器Action方法的参数,那么也用这个属性名来自动获取http请求参数值。 总之此方法返回的属性名是相当重要的。 其他三个方法并不常用,通常是返回null就可以了, 如果数据库不支持auto_increment(比如Oracle就不支持), 那么可以为此列单独建个序列,用getSequenceName方法返回此序列名, Douyu就会自动根据这个序列名来模拟auto_increment,这样就可以自动填充主键值了。 但是为每个列单独建个序列这可能太浪费了,所以这个方法并不常用, Douyu提供了一个配置参数:defaultSequenceName,默认是"douyu_sequence", 如果getSequenceName方法返回null,对应的表中又存在主键, 并且还把另一个配置参数:autoFillPrimaryKey设为true了, 当你在增加记录时,如果没有提供主键值,Douyu就会根据序列名来自动生成一个主键值。 getSQLEventListener方法用来返回一个com.douyu.sql.SQLEventListener接口的实现类名, 这样你可以监听对应的模型类的一些事件,SQLEventListener接口定义了如下方法: void beforeInsert(Context context, Object entity); void beforeUpdate(Context context, Object entity); void beforeDelete(Context context, Object entity); void afterInsert(Context context, Object entity); void afterUpdate(Context context, Object entity); void afterDelete(Context context, Object entity); getPropertyListener方法用来返回一个com.douyu.sql.PropertyListener接口的实现类名, 这样你可以监听对应的模型类中某个属性的事件,PropertyListener接口定义了如下方法: void init(Context context); Object getPropertyValue(Object entity, String propertyName, Object oldPropertyValue); Object setPropertyValue(Object entity, String propertyName, Object newPropertyValue); init方法只在模型类作为控制器Action方法的参数时有用, 此时初始化模型类时会同时初始化PropertyListener,并通过init方法把Context传给PropertyListener, 其他两个方法的作用类似这样(假定name是某个模型类的属性): public String getName() { return (String)propertyListener.getPropertyValue(this,"name",this.name); } public void setName(String name) { this.name = (String)propertyListener.setPropertyValue(this,"name",name); } 最后,请修改服务器的配置文件, 在相应的@Database数据库配置项中加上一个参数: databaseMapping = "pck.MyDatabaseMapping", 当然了,你必须把"pck.MyDatabaseMapping"改成你自己的类名,类名前面要加包名。 |
|
返回顶楼 | |
发表时间:2009-11-15
2.9.6 自动校验 Douyu内置了一个简单的自动校验功能, 如果把模型类作为控制器Action方法的参数,那么就会自动启用自动校验功能, 自动校验目的是为了维护表中数据的完整性和正确性, 只有校验全部通过后,才允许对表进行更新操作, 你可以通过com.douyu.main.Context接口的 public List<ContextMessage> getContextMessageList(); 来获得所有的校验失败消息. com.douyu.main.ContextMessage类的完整代码如下: package com.douyu.main; public class ContextMessage { //通过组合这四个字段,你可以定义出更具体化的消息 Class enclosingClass; //一般是对应的模型类 String propertyName; //属性名 String propertyValue; //属性值(一般是从http请求中获得的不合法的参数值) String message; //一条本地化的简短消息(比如不能为空,或必须是数字等等) public ContextMessage() { } public ContextMessage(String propertyName, String propertyValue, String message) { this.propertyName = propertyName; this.propertyValue = propertyValue; this.message = message; } public ContextMessage(Class enclosingClass, String propertyName, String propertyValue, String message) { this.enclosingClass = enclosingClass; this.propertyName = propertyName; this.propertyValue = propertyValue; this.message = message; } public void setEnclosingClass(Class enclosingClass) { this.enclosingClass = enclosingClass; } public void setPropertyName(String propertyName) { this.propertyName = propertyName; } public void setPropertyValue(String propertyValue) { this.propertyValue = propertyValue; } public void setMessage(String message) { this.message = message; } public Class getEnclosingClass() { return enclosingClass; } public String getPropertyName() { return propertyName; } public String getPropertyValue() { return propertyValue; } public String getMessage() { return message; } public String toString() { StringBuilder s = new StringBuilder("ContextMessage[propertyName="); s.append(propertyName) .append(", propertyValue=").append(propertyValue) .append(", message=").append(message) .append(", enclosingClass=").append(enclosingClass).append("]"); return s.toString(); } } |
|
返回顶楼 | |
发表时间:2009-11-16
很好、很强大
很感兴趣的是应用服务器这块,非常好 令人钦佩的老鸟 |
|
返回顶楼 | |
发表时间:2009-11-16
楼主是疯子+技术狂人,不加精说不过去了!!
虽然看的我蒙蒙的,哈哈。国内期待有这样的大牛来开天辟地啊。 |
|
返回顶楼 | |
发表时间:2009-11-16
超佩服你的耐力和执着精神,不过的确看的我晕、、、深奥
|
|
返回顶楼 | |
发表时间:2009-11-16
linliangyi2007 写道 楼主是疯子+技术狂人,不加精说不过去了!!
虽然看的我蒙蒙的,哈哈。国内期待有这样的大牛来开天辟地啊。 深有同感,很狂,很牛。。。。 |
|
返回顶楼 | |
发表时间:2009-11-16
无论Douyu最后的结果如何,楼主的对技术执着令人钦佩
|
|
返回顶楼 | |
发表时间:2009-11-16
真有时间啊。
|
|
返回顶楼 | |
发表时间:2009-11-16
引用 那三个月内时常有沮丧感,似乎已走近了死胡同! 后来心一狠,决心甩开JSP/Servlet那一堆条条框框,把设计的起点再往下深一个层次。 无数牛人都是死在这里的吧!但楼主突破了,杀出了一条血路 真是了不起,真是了不起! |
|
返回顶楼 | |
发表时间:2009-11-16
这是从服务器入手,直接支持
|
|
返回顶楼 | |