Android ORM数据库框架之-greenDao(三)

关于上篇说到的数据库更新问题,我正在找国外大牛的二次封装的github代码。找到会贴出来。
咱们这篇,小小地分析下greendao-generator的源码,和大家一起了解下,代码的生成。

咱们写的java项目代码很简单,就是个初始化Schema——>添加Entity
——>生成的过程。

  • Schema
    我们看下我们写的代码
Schema schema = new Schema(2,"gl.com.greendaodemo");

很简单,就是版本号+生成代码包名。
我们看下Schema的部分源码。

private final int version;
    private final String defaultJavaPackage;
    private String defaultJavaPackageDao;
    private String defaultJavaPackageTest;
    private final List<Entity> entities;
    private Map<PropertyType, String> propertyToDbType;
    private Map<PropertyType, String> propertyToJavaTypeNotNull;
    private Map<PropertyType, String> propertyToJavaTypeNullable;
    private boolean hasKeepSectionsByDefault;
    private boolean useActiveEntitiesByDefault;

    public Schema(int version, String defaultJavaPackage) {
        this.version = version;
        this.defaultJavaPackage = defaultJavaPackage;
        this.entities = new ArrayList<Entity>();
        initTypeMappings();
    }

看得出,构造函数就是初始化了数据库版本、包名、实体list以及属性类型(initTypeMappings()来完成属性类型初始化),下面贴出这个函数的部分代码

propertyToDbType = new HashMap<PropertyType, String>();
        propertyToDbType.put(PropertyType.Boolean, "INTEGER");
        propertyToDbType.put(PropertyType.Byte, "INTEGER");
        propertyToDbType.put(PropertyType.Short, "INTEGER");
        propertyToDbType.put(PropertyType.Int, "INTEGER");
        propertyToDbType.put(PropertyType.Long, "INTEGER");
        propertyToDbType.put(PropertyType.Float, "REAL");
        propertyToDbType.put(PropertyType.Double, "REAL");
        propertyToDbType.put(PropertyType.String, "TEXT");
        propertyToDbType.put(PropertyType.ByteArray, "BLOB");
        propertyToDbType.put(PropertyType.Date, "INTEGER");

Schema的初始化看完了,接下来我们看下如何添加实体

  • Entity以及addEntity
Entity people = schema.addEntity("People");
        people.addStringProperty("name").primaryKey(); //名字
        people.addIntProperty("age"); //年龄

上面是添加一个实体的过程,我们瞅瞅addEntity();函数

public Entity addEntity(String className) {
        Entity entity = new Entity(this, className);
        entities.add(entity);
        return entity;
    }

嗯,简单 ,就是给list添加了一个对象。。。那么,给实体添加约束的源码又是什么呢?我们以addIdProperty()为例。

public PropertyBuilder addIdProperty() {
        PropertyBuilder builder = addLongProperty("id");
        builder.columnName("_id").primaryKey();
        return builder;
    }

可以看到,这里直接将给了个_id的列并作为主键存在。上面有用到PropertyBuilder这个类,这个是干什么的?
,偶,这个类就是给数据库中的字段设置约束的。看到,有自增、非空、主键等等。

person.addStringProperty("name")

我们看看如何给字段指定类型。上面 的哪一行代码 最终会调用 下面这个构造函数。可以看到,这里就有了字段类型了,那么字段类型又有哪些呢,还记得我们在初始化Schema的时候的代码么,没错,就是那些。但是,光那些是不够用的,greendao还支持我们自定义。请移步官方介绍

public Property(Schema schema, Entity entity, PropertyType propertyType, String propertyName) {
        this.schema = schema;
        this.entity = entity;
        this.propertyName = propertyName;
        this.propertyType = propertyType;
    }

接下来便是重头戏,代码生成部分

  • 代码生成
  • -
new DaoGenerator().generateAll(schema, "/Users/mac/Desktop/GLandroidstudy/AS/greendaodemo/src/main/java-gen");

我们看看DaoGenerator的构造函数

public DaoGenerator() throws IOException {
        System.out.println("greenDAO Generator");
        System.out.println("Copyright 2011-2015 Markus Junginger, greenrobot.de. Licensed under GPL V3.");
        System.out.println("This program comes with ABSOLUTELY NO WARRANTY");

        patternKeepIncludes = compilePattern("INCLUDES");
        patternKeepFields = compilePattern("FIELDS");
        patternKeepMethods = compilePattern("METHODS");

        Configuration config = new Configuration();
        config.setClassForTemplateLoading(this.getClass(), "/");
        config.setObjectWrapper(new DefaultObjectWrapper());

        templateDao = config.getTemplate("dao.ftl");
        templateDaoMaster = config.getTemplate("dao-master.ftl");
        templateDaoSession = config.getTemplate("dao-session.ftl");
        templateEntity = config.getTemplate("entity.ftl");
        templateDaoUnitTest = config.getTemplate("dao-unit-test.ftl");
        templateContentProvider = config.getTemplate("content-provider.ftl");
    }

那个.ftl文件是什么呢?.ftl是Freemarker文件的后缀名,是个模版语言引擎。关于Freemarker更多介绍,自行百度。我们以entity.ftl为例,简单介绍几行。

public class ${entity.className}<#if
entity.superclass?has_content> extends ${entity.superclass} </#if><#if
entity.interfacesToImplement?has_content> implements <#list entity.interfacesToImplement
as ifc>${ifc}<#if ifc_has_next>, </#if></#list></#if> {

<#list entity.properties as property>
<#if property.notNull && complexTypes?seq_contains(property.propertyType)>
    /** Not-null value. */
</#if>
<#if property.codeBeforeField ??>
     ${property.codeBeforeField}
</#if>
    private ${property.javaTypeInEntity} ${property.propertyName};
</#list>

上面的结果就是

private class classname (extends supperclass )(implements interface){
    private type property;
    ...
}

就是输出类似上面的东西,其实语法很简单,就是根据传进来的entity实体,根据entity实体的内容来讲${}部分用对应的东西替代,最后就输出成我们的文件了。好,就这么多把,我们再来看下generateAll()的代码。

public void generateAll(Schema schema, String outDir, String outDirEntity, String outDirTest) throws Exception {
        long start = System.currentTimeMillis();

        File outDirFile = toFileForceExists(outDir);
        File outDirEntityFile = outDirEntity != null? toFileForceExists(outDirEntity): outDirFile;
        File outDirTestFile = outDirTest != null ? toFileForceExists(outDirTest) : null;

        schema.init2ndPass();
        schema.init3rdPass();

        System.out.println("Processing schema version " + schema.getVersion() + "...");

        List<Entity> entities = schema.getEntities();
        for (Entity entity : entities) {
            generate(templateDao, outDirFile, entity.getJavaPackageDao(), entity.getClassNameDao(), schema, entity);
            if (!entity.isProtobuf() && !entity.isSkipGeneration()) {
                generate(templateEntity, outDirEntityFile, entity.getJavaPackage(), entity.getClassName(), schema, entity);
            }
            if (outDirTestFile != null && !entity.isSkipGenerationTest()) {
                String javaPackageTest = entity.getJavaPackageTest();
                String classNameTest = entity.getClassNameTest();
                File javaFilename = toJavaFilename(outDirTestFile, javaPackageTest, classNameTest);
                if (!javaFilename.exists()) {
                    generate(templateDaoUnitTest, outDirTestFile, javaPackageTest, classNameTest, schema, entity);
                } else {
                    System.out.println("Skipped " + javaFilename.getCanonicalPath());
                }
            }
            for (ContentProvider contentProvider : entity.getContentProviders()) {
                Map<String, Object> additionalObjectsForTemplate = new HashMap<String, Object>();
                additionalObjectsForTemplate.put("contentProvider", contentProvider);
                generate(templateContentProvider, outDirFile, entity.getJavaPackage(), entity.getClassName()
                        + "ContentProvider", schema, entity, additionalObjectsForTemplate);
            }
        }
        generate(templateDaoMaster, outDirFile, schema.getDefaultJavaPackageDao(), "DaoMaster", schema, null);
        generate(templateDaoSession, outDirFile, schema.getDefaultJavaPackageDao(), "DaoSession", schema, null);

        long time = System.currentTimeMillis() - start;
        System.out.println("Processed " + entities.size() + " entities in " + time + "ms");
    }

最后都会调用上面的一段代码,上面的代码在做什么呢。显示创建几个文件夹,然后遍历List< Entity>,输出内容的

generate(templateEntity, outDirEntityFile, entity.getJavaPackage(), entity.getClassName(), schema, entity);

就是根据传进来的末班,包名,类名,schema,实体,替换掉模板中对应的,输出。关于具体输出的源码,实在是太长了,童鞋们自己看吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值