一、数据库模块(2)实战

上一篇文章地址: //www.greatytc.com/p/ef159add53ed

这一章梳理一下整个数据库模块内部协作的流程:

相互关系

图中 我特意用两种不同的颜色划分两个不同的功能--黑色和红色部分

黑色部分

模块的工作的第一部分是黑色部分,他的功能较为简单,也就是以autogenerate模块作为主导,通过 db模块连接数据库,并且通过查询结果映射生成 dojo部分可以用来查询的类。也就是:

  autogenerate ----->请求连接数据库------>db------->执行查询,并将结果返回-------->autogenerate收到查询结果----------->生成对应的dojo类,这也就是之前文章提到的danmaku.java文件的由来

黑色部分已经在上一篇文章中有例子了,现在重点讲述红色部分的逻辑。

红色部分

不知道大家对于上一篇文章的此处是否还有印象?

Danmaku danmaku = new Danmaku().roomidEqual(45).get();

要获取roomid为45的弹幕居然就一行就能解决,还不用处理sql查询之后的将对应字段放入类的属性中,是不是感觉很神奇?反正我那时候是觉得听神奇的。
这幕后功臣是Bean模块,在之前的介绍中也提到他是负责类的存取属性等操作。以下是他的主要类:

package com.angroid.bean;

import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.json.JSONObject;

import com.angroid.dojo.DojoImpl;
import com.angroid.html.Element;
import com.angroid.web.MultiPartRequest;

public class BeanFactory {
    
    /**
     * 为不同类型的对象,选择对应封装操作类
     * @param obj
     * @return
     */
    public static Bean newBean(Object obj){
        
        if (obj instanceof Bean){
            return (Bean)obj;
        }

        if(obj instanceof Map){
            return new BeanMap((Map) obj);
        }
        
        if(obj instanceof ResultSet){
            return new BeanResultSet((ResultSet) obj);
        }

        if(obj instanceof MultiPartRequest){
            return new BeanRequest((MultiPartRequest) obj);
        }

        if(obj instanceof HttpSession){
            return new SessionBean((HttpSession) obj);
        }
        
        if(obj instanceof DojoImpl){
            return new DojoBean(obj);
        }

        if (obj instanceof Element){
            return new ElementBean((Element)obj);
        }
        
        if (obj instanceof JSONObject){
            return new BeanJSONObject((JSONObject)obj);
        }
        
        return new BeanObject(obj);
    }
    

    public static Map toMap(Object obj){
        
        Map r = new HashMap();
        Bean b = newBean(r);
        b.setAll(obj);
        return r;

    }
}

这里使用的是设计模式中的工厂模式,需要什么的时候就通过工厂造出来。我们关注BeanObject这个类,他是实现我们文章开头那一行语句的关键。

package com.angroid.bean;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.angroid.cast.CasterFactory;

/**
 * 实现BeanBase接口,普通的java类
 * @author Alien
 *
 */
public class BeanObject extends BeanBase {

    Object object;

    Map<String, Field> fieldMap = new HashMap();

    /**
     * 获取映射关系
     * @return
     */
    public Map<String, Field> getFieldMap() {
        return fieldMap;
    }

    /**
     * 构造函数,生成所有的映射(成员与名字)
     * @param obj
     */
    public BeanObject(Object obj) {
        this.object = obj;
        Field[] fields = obj.getClass().getFields();
        for (Field f : fields) {
            String name = getFieldName(f);
            fieldMap.put(name, f);
        }
    }

    /**
     * 获取字段名
     * @param f
     * @return
     */
    public static String getFieldName(Field f) {

//      SessionAttribute a = f.getAnnotation(SessionAttribute.class);
//      if (a != null && a.Name() != null && a.Name().length() > 0) {
//          return a.Name();
//      }
//
//      Parameter p = f.getAnnotation(Parameter.class);
//      if (p != null && p.Name() != null && p.Name().length() > 0) {
//          return p.Name();
//      }

        return f.getName();
    }

    /**
     * 获取字段名对应的值
     */
    @Override
    public Object get(String name) {
        
        if(name == null)return null;
        
        String[] names = name.split("\\.", 2);
        if(names.length==2){
            Object object = get(names[0]);
            if(object == null){
                return null;
            }
            return BeanFactory.newBean(object).get(names[1]);
        }
        
        
        Field field = fieldMap.get(name);
        if (field == null)
            return null;
        try {
            return field.get(object);
        } catch (IllegalArgumentException e) {
            System.err.println("exception: object " + object + " field " + name
                    + " illegal argument");
        } catch (IllegalAccessException e) {
            System.err.println("exception object " + object + " field " + name
                    + " not public");
        }
        return null;
    }

    /**
     * 是否包含字段名?
     */
    @Override
    public boolean contains(String key) {
        return fieldMap.containsKey(key);
    }

    /**
     * 设置字段的值
     */
    @Override
    public void set(String name, Object value) {

        if (value == null)
            return;

        String[] names = name.split("\\.", 2);
        if(names.length==2){
            Object object = get(names[0]);
            if(object == null){
                return;
            }
            BeanFactory.newBean(object).set(names[1], value);
            return;
        }
        
        try {
            Field field = fieldMap.get(name);
            
            if(field==null){
                return;
            }

            if (field.getType() != value.getClass()) {
                if (value.getClass() != String.class) {
                    value = value.toString();
                }
                
                if (field.getType().isArray()) {

                    Class cls = field.getType().getComponentType();

                
                    if (cls == Integer.class) {
                        
                        String[] ss = value.toString().split(",");
                        
                        Integer[] t = new Integer[ss.length];
                        
                        for(int i=0;i<ss.length;i++){
                            t[i] = Integer.valueOf(ss[i], 10);
                        }
                        field.set(object, t);
                        return;
                    }

                    if (cls == Float.class) {
                        
                        String[] ss = value.toString().split(",");
                        
                        Float[] t = new Float[ss.length];
                        
                        for(int i=0;i<ss.length;i++){
                            t[i] = Float.valueOf(ss[i]);
                        }
                        field.set(object, t);
                        return;
                    }

                    if (cls == String.class) {
                        
                        String[] ss = value.toString().split(",");
                        
                        field.set(object, ss);
                        return;
                    }
                    
                }

                value = CasterFactory
                        .valueOf(field.getType(), (String) value);
            }

            field.set(object, value);
        } catch (Exception e) {
            System.out.println("exception: "+name);
            e.printStackTrace();
        }
    }


    @Override
    public Set keySet() {
        return fieldMap.keySet();
    }

    @Override
    public Object get() {
        return object;
    }

}

可以看出,这个类的作用就是将一个key-value的Map映射到对应的java类属性中,这也是业务层前端实现的。(如果想更加详细的了解,请阅读源码)

此外db模块对于那些没有对应java类的查询也做了一层封装处理(转为为Map的链表),例如下面我只想获取弹幕的昵称还有内容,不需要将所有字段返回,可以这么写:

package alien.art;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.Request;
import org.apache.catalina.tribes.group.interceptors.TwoPhaseCommitInterceptor.MapEntry;

import com.angroid.autogenerate.handler.vericode;
import com.angroid.db.SQLExecutor;
import com.angroid.dojo.Danmaku;
import com.angroid.dojo.Room;

public class test{
    
    public static void main(String[] args) {
        

        List<Map> res = SQLExecutor.find("select nickname, content from danmaku where id = 13");
        for(Map map : res) {
            if(map.containsKey("nickname"))
                System.out.println("nickname: " + map.get("nickname"));
            if(map.containsKey("content"))
                System.out.println("content: " + map.get("content"));
        }
    }

}

/*返回结果
select nickname, content from danmaku where id = 13
[]
word: select
word: nickname
word: content
word: from
word: danmaku
word: where
nickname: 仙女爸爸0818
content: 我的小妲己不敢玩了

*/

至此,数据库模块再也没有什么秘密了,只要再仔细阅读源码能更加明白作者的意图。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容