Я хотел бы знать, что означает ошибка из заголовка - она очень часто встречается в моем проекте, но не имеет абсолютно никакого смысла (очевидно, что связанные классы являются более нервными примитивными типами).
Мне кажется, что эта ошибка возникает, если некоторые отношения неправильно сконфигурированы (например, имя внешнего поля с ошибкой в аннотации), но ошибка не дает никакой информации об этом. Поиск этих неправильных отношений занимает так много времени, что я мог бы потратить это время на написание моей модели в простом 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;
}
}
Вкладка 2:
@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 я создаю дао:
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)
Кроме того, у меня есть собственные дао для всех других классов в модели, но я не использую их для этих двух классов. У меня также есть интерфейс для каждого другого класса в модели (я знаю, что это странно, но для некоторых целей он должен быть у меня).
Любая помощь будет принята с благодарностью, спасибо!