Ormlite:FieldType是基本类型,但标记为外来类型

时间:2013-03-14 10:38:03

标签: android ormlite

我想知道,标题中的错误是什么意思 - 它经常发生在我的项目中,但它绝对没有感觉(显然,相关的类是神经元原始类型)。

在我看来,如果某些关系配置错误(例如注释中拼写错误的外部字段名称),则会抛出此错误 - 但错误不会提供有关它的信息。找到那些错误的关系是非常耗时的,我可以花这段时间在没有任何orm的普通sql中编写我的模型!

我也遇到了一个奇怪的情况,我没有看到任何错误 - 但是“原始类型标记为外来”异常再次被抛出。以下是这种情况。

沿着模型中的许多表(大约50个类),我创建了这两个: TAB1:

@DatabaseTable()
public class Tab1 {
    @DatabaseField(generatedId = true)
    int id;

    @ForeignCollectionField(eager = false, foreignFieldName = "tab1")
    Collection<Tab2> tab2;

    public Tab1() {
    }

    public int getId() {
            return id;
    }

    public void setId(int id) {
            this.id = id;
    }

    public Collection<Tab2> getTab2() {
            return tab2;
    }
}

TAB2:

@DatabaseTable()
public class Tab2 {
    @DatabaseField(generatedId = true)
    int id;

    @DatabaseField(foreign = true)
    Tab1 tab1;

    public Tab2() {
    }

    public Tab2(Tab1 tab1) {
            super();
            this.tab1 = tab1;
    }

    public int getId() {
            return id;
    }

    public void setId(int id) {
            this.id = id;
    }

    public Tab1 getTab1() {
            return tab1;
    }

    public void setTab1(Tab1 tab1) {
            this.tab1 = tab1;
    }
}

在DatabaseHelper中我创建了daos:

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

    private static final String DATABASE_NAME = "samplename.db";
    private static final String BACKUP_DATABASE_NAME = "samplename_bak.db";
    private static final int DATABASE_VERSION = 2;
    private static String DB_PATH = "/data/data/com.samplepath/databases/";

// DAOs

Dao<Tab1, Integer> tab1Dao;
Dao<Tab2, Integer> tab2Dao;
    // many other daos

    public Dao<Tab1, Integer> getTab1Dao() {
            try {
                    if (tab1Dao == null) {
                            tab1Dao = DaoManager.createDao(connectionSource, Tab1.class);
                    }
                    return tab1Dao;
            } catch (SQLException e) {
                    return null;
            }
    }

    public Dao<Tab2, Integer> getTab2Dao() {
            try {
                    if (tab2Dao == null) {
                            tab2Dao = DaoManager.createDao(connectionSource, Tab2.class);
                    }
                    return tab2Dao;
            } catch (SQLException e) {
                    return null;
            }
    }
    //many other dao getters

    public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION, R.raw.ormlite_config);
            Log.i("dbTag", "Creating database from file...");
            SQLiteDatabase db = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
            try {
                    Log.i("dbTag", "Creating database....");
                    TableUtils.createTable(connectionSource, Tab1.class);
                    TableUtils.createTable(connectionSource, Tab2.class);
                    //other create tables
                    Log.i("Exception", "inserted");
            } catch (SQLException e) {
                    Log.i("Exception", "error - could not create database.");
                    Log.i("Exception", e.getMessage());
                    Log.e("Exception", "", e);
            }
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int oldVersion,
                    int newVersion) {
            try {
                    Log.i("dbTag", "onUpgrade");
                    Log.i("dbTag", "Dropping database....");
                    TableUtils.dropTable(connectionSource, Tab1.class, true);
                    TableUtils.dropTable(connectionSource, Tab2.class, true);
                    //other drops
                    Log.i("dbTag", "Creating database....");
                    onCreate(sqLiteDatabase, connectionSource);
            } catch (SQLException e) {
                    Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e);
                    throw new RuntimeException(e);
            }
    }
}

我还在config util中包含了这两个类,并创建了ormlite_config.txt文件。 我在基本活动中管理数据库助手以及roboguice:

public class BaseActivity<T extends OrmLiteSqliteOpenHelper, E extends BaseErrorHandler> extends OrmLiteBaseActivity<T> implements RoboContext, IErrorHandler {

    protected EventManager eventManager;
    protected HashMap<Key<?>,Object> scopedObjects = new HashMap<Key<?>,Object>();
    protected E errorHandler;
    public static final DefaultHttpClient httpclient = new DefaultHttpClient();
    public static Map<String,String> args = null;

    @Inject
    ContentViewListener ignored; // do not use?

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        final RoboInjector injector = RoboGuice.getInjector(this);
        eventManager = injector.getInstance(EventManager.class);
        injector.injectMembersWithoutViews(this);
        super.onCreate(savedInstanceState);
        eventManager.fire(new OnCreateEvent(savedInstanceState));
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        eventManager.fire(new OnRestartEvent());
    }

    @Override
    protected void onStart() {
        super.onStart();
        eventManager.fire(new OnStartEvent());
    }

    @Override
    protected void onResume() {
        super.onResume();
        eventManager.fire(new OnResumeEvent());
    }

    @Override
    protected void onPause() {
        super.onPause();
        eventManager.fire(new OnPauseEvent());
    }

    @Override
    protected void onNewIntent( Intent intent ) {
        super.onNewIntent(intent);
        eventManager.fire(new OnNewIntentEvent());
    }

    @Override
    protected void onStop() {
        try {
            eventManager.fire(new OnStopEvent());
        } finally {
            super.onStop();
        }
    }

    @Override
    protected void onDestroy() {
        try {
            eventManager.fire(new OnDestroyEvent());
        } finally {
            try {
                RoboGuice.destroyInjector(this);
            } finally {
                super.onDestroy();
            }
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        final Configuration currentConfig = getResources().getConfiguration();
        super.onConfigurationChanged(newConfig);
        eventManager.fire(new OnConfigurationChangedEvent(currentConfig, newConfig));
    }

    @Override
    public void onContentChanged() {
        super.onContentChanged();
        RoboGuice.getInjector(this).injectViewMembers(this);
        eventManager.fire(new OnContentChangedEvent());
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        eventManager.fire(new OnActivityResultEvent(requestCode, resultCode, data));
    }

    public Map<Key<?>, Object> getScopedObjectMap() {
        return scopedObjects;
    }

    @Override
    public void handleError(int resId) {
        errorHandler.exceptionHandler(getString(resId), this);
    }

}

在午餐活动中,我运行代码:

Log.i("Tab1", "creating tab1");
getHelper().getTab1Dao();
Log.i("Tab1", "created tab1");
Log.i("Tab1", "creating tab2");
getHelper().getTab2Dao();
Log.i("Tab1", "created tab2");

首先从设备上卸载该应用,然后再安装并运行该应用。这就是我在日志中看到的内容:

03-14 11:22:54.400: I/DaoManager(31657): Loaded configuration for class com.xxx.xxx.model.Tab1
03-14 11:22:54.400: I/DaoManager(31657): Loaded configuration for class com.xxx.xxx.model.Tab2
03-14 11:22:54.423: I/dbTag(31657): Creating database from file...
03-14 11:22:54.486: I/dbTag(31657): Creating database....
03-14 11:22:54.494: I/TableUtils(31657): creating table 'tab1'
03-14 11:22:54.494: I/TableUtils(31657): executed create table statement changed 1 rows: CREATE TABLE `tab1` (`id` INTEGER PRIMARY KEY AUTOINCREMENT ) 
03-14 11:22:54.494: I/TableUtils(31657): creating table 'tab2'
03-14 11:22:54.501: I/TableUtils(31657): executed create table statement changed 1 rows: CREATE TABLE `tab2` (`id` INTEGER PRIMARY KEY AUTOINCREMENT , `tab1_id` INTEGER ) 
[...]
03-14 11:22:55.283: I/Tab1(31657): creating tab1
03-14 11:22:55.291: E/Tab1(31657): java.lang.IllegalArgumentException: Field FieldType:name=tab1,class=Tab2 is a primitive class class com.xxx.xxx.model.Tab1 but marked as foreign
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.field.FieldType.configDaoInformation(FieldType.java:315)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.BaseDaoImpl.initialize(BaseDaoImpl.java:200)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.BaseDaoImpl.<init>(BaseDaoImpl.java:126)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.BaseDaoImpl.<init>(BaseDaoImpl.java:117)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.BaseDaoImpl$5.<init>(BaseDaoImpl.java:911)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.BaseDaoImpl.createDao(BaseDaoImpl.java:911)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.DaoManager.doCreateDao(DaoManager.java:359)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.DaoManager.createDaoFromConfig(DaoManager.java:326)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.dao.DaoManager.createDao(DaoManager.java:55)
03-14 11:22:55.291: E/Tab1(31657):  at com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper.getDao(OrmLiteSqliteOpenHelper.java:239)
03-14 11:22:55.291: E/Tab1(31657):  at com.xxx.xxx.xxx.onCreate(XXX.java:43)
03-14 11:22:55.291: E/Tab1(31657):  at android.app.Activity.performCreate(Activity.java:4465)
03-14 11:22:55.291: E/Tab1(31657):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053)
03-14 11:22:55.291: E/Tab1(31657):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934)
03-14 11:22:55.291: E/Tab1(31657):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
03-14 11:22:55.291: E/Tab1(31657):  at android.app.ActivityThread.access$600(ActivityThread.java:128)
03-14 11:22:55.291: E/Tab1(31657):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
03-14 11:22:55.291: E/Tab1(31657):  at android.os.Handler.dispatchMessage(Handler.java:99)
03-14 11:22:55.291: E/Tab1(31657):  at android.os.Looper.loop(Looper.java:137)
03-14 11:22:55.291: E/Tab1(31657):  at android.app.ActivityThread.main(ActivityThread.java:4514)
03-14 11:22:55.291: E/Tab1(31657):  at java.lang.reflect.Method.invokeNative(Native Method)
03-14 11:22:55.291: E/Tab1(31657):  at java.lang.reflect.Method.invoke(Method.java:511)
03-14 11:22:55.291: E/Tab1(31657):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
03-14 11:22:55.291: E/Tab1(31657):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
03-14 11:22:55.291: E/Tab1(31657):  at dalvik.system.NativeStart.main(Native Method)

此外,我对模型中的所有其他类都有自定义daos,但我不会将它们用于这两个类。我也有模型中每个其他类的接口(我知道这很奇怪,但我必须将它用于某些目的)。

非常感谢任何帮助,谢谢!

3 个答案:

答案 0 :(得分:1)

咦。那么错误假设是自我解释

Field FieldType:name=tab1,class=Tab2 is a primitive class 
    class com.xxx.xxx.model.Tab1 but marked as foreign

由于某种原因,Tab2类型将tab1字段标记为原始类。但是,在您的课程中,tab1字段定义为:

@DatabaseField(foreign = true)
Tab1 tab1;

您是否有可能未更新与此类关联的数据库配置文件?也许使用成为int,现在它是Tab1?更改架构时,需要重新生成配置文件。

答案 1 :(得分:0)

我遇到了同样的问题,虽然我不知道究竟是什么问题,但我确定它是由ormlite_config.txt文件引起的。删除文件后,将数据库助手类的构造函数更改为不使用ormlite_config.txt版本。一切都很好。

答案 2 :(得分:-1)

如果有人遇到类似的问题:不要在DatabaseHelper的构造函数中调用this.getWritableDatabase()。当我删除它时,代码神奇地开始工作 - 不知道,为什么会发生,但它确实有效。