greenDao 在 qigsaw中报错Could not init DAOConfig

Posted 许佳佳233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了greenDao 在 qigsaw中报错Could not init DAOConfig相关的知识,希望对你有一定的参考价值。

报错

org.greenrobot.greendao.DaoException: Could not init DAOConfig

场景

  • 使用qigsaw
  • 宿主模块依赖 greenDAO
  • 插件模块使用了greenDAO
  • 插件模块使用greenDAO报错:Could not init DAOConfig

原因

  • greenDAO源码中通过反射的方式去调用Properties类
  • 宿主模块加载greenDAO的ClassLoader是 PathClassLoader
  • 插件模块加载AbstractDao实现类的ClassLoader是 QigsawClassLoader
  • 由于QigsawClassLoader中没有加载DAOConfig,于是会报错。

排查方式

排查方式就是查看greenDAO源码,由于是插件化导致的崩溃,所以很快可以推断是ClassLoader的问题,验证后发现果然是。

    public DaoConfig(Database db, Class<? extends AbstractDao<?, ?>> daoClass) {
        this.db = db;
        try {
            this.tablename = (String) daoClass.getField("TABLENAME").get(null);
            Property[] properties = reflectProperties(daoClass);
            this.properties = properties;

            allColumns = new String[properties.length];

            List<String> pkColumnList = new ArrayList<String>();
            List<String> nonPkColumnList = new ArrayList<String>();
            Property lastPkProperty = null;
            for (int i = 0; i < properties.length; i++) {
                Property property = properties[i];
                String name = property.columnName;
                allColumns[i] = name;
                if (property.primaryKey) {
                    pkColumnList.add(name);
                    lastPkProperty = property;
                } else {
                    nonPkColumnList.add(name);
                }
            }
            String[] nonPkColumnsArray = new String[nonPkColumnList.size()];
            nonPkColumns = nonPkColumnList.toArray(nonPkColumnsArray);
            String[] pkColumnsArray = new String[pkColumnList.size()];
            pkColumns = pkColumnList.toArray(pkColumnsArray);

            pkProperty = pkColumns.length == 1 ? lastPkProperty : null;
            statements = new TableStatements(db, tablename, allColumns, pkColumns);

            if (pkProperty != null) {
                Class<?> type = pkProperty.type;
                keyIsNumeric = type.equals(long.class) || type.equals(Long.class) || type.equals(int.class)
                        || type.equals(Integer.class) || type.equals(short.class) || type.equals(Short.class)
                        || type.equals(byte.class) || type.equals(Byte.class);
            } else {
                keyIsNumeric = false;
            }

        } catch (Exception e) {
            throw new DaoException("Could not init DAOConfig", e);
        }
    }

    private static Property[] reflectProperties(Class<? extends AbstractDao<?, ?>> daoClass)
            throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException {
        Class<?> propertiesClass = Class.forName(daoClass.getName() + "$Properties");
        Field[] fields = propertiesClass.getDeclaredFields();

        ArrayList<Property> propertyList = new ArrayList<Property>();
        final int modifierMask = Modifier.STATIC | Modifier.PUBLIC;
        for (Field field : fields) {
            // There might be other fields introduced by some tools, just ignore them (see issue #28)
            if ((field.getModifiers() & modifierMask) == modifierMask) {
                Object fieldValue = field.get(null);
                if (fieldValue instanceof Property) {
                    propertyList.add((Property) fieldValue);
                }
            }
        }

        Property[] properties = new Property[propertyList.size()];
        for (Property property : propertyList) {
            if (properties[property.ordinal] != null) {
                throw new DaoException("Duplicate property ordinals");
            }
            properties[property.ordinal] = property;
        }
        return properties;
    }

解决方案

解决方案还是很多的,主要还是根据业务需要来。笔者就抛砖引玉写一些可能的方案:

  1. 将插件中greenDAO的相关逻辑放到宿主模块中
  2. 如果插件中greenDAO中逻辑不多,作为临时方案,可以将greenDAO调用到的类在宿主中重复定义一遍。(只能是临时方案)
  3. 如宿主中没有使用greenDao的逻辑,可以改成插件直接依赖,而不要在宿主中加载。

以上是关于greenDao 在 qigsaw中报错Could not init DAOConfig的主要内容,如果未能解决你的问题,请参考以下文章

greenDao 在 qigsaw中报错Could not init DAOConfig

ThinkPHP5.0中报错could not find driver的解决方式

ssm中报错: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type a

在添加greendao 的plugin 出现?:Could not initialize class com.android.sdklib.repository.AndroidSdkHandler

Android之Fatal Exception: org.greenrobot.greendao.DaoException: Could not init DAOConfig

json数据格式在IE浏览器中报错问题