Ciekawy problem z ORMLite

blog.lantkowiak.pl 8 lat temu

Podczas implementacji ekranu edycji dokumentu natknąłem się na interesujący błąd związany z ORM.

Podczas próby aktualizacji encji

DocumentFile

otrzymałem poniższy błąd:

pl.lantkowiak.sdm E/AndroidRuntime: FATAL EXCEPTION: main java.lang.RuntimeException: java.sql.SQLException: Cannot update class pl.lantkowiak.sdm.core.entity.DocumentFile because it doesn't have an id field at com.j256.ormlite.dao.RuntimeExceptionDao.update(RuntimeExceptionDao.java:264) at pl.lantkowiak.sdm.activities.EditDocumentActivity$$anonfun$updateFiles$2.apply(EditDocumentActivity.scala:134) at pl.lantkowiak.sdm.activities.EditDocumentActivity$$anonfun$updateFiles$2.apply(EditDocumentActivity.scala:130) at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59) at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48) at pl.lantkowiak.sdm.activities.EditDocumentActivity.updateFiles(EditDocumentActivity.scala:130) at pl.lantkowiak.sdm.activities.EditDocumentActivity.updateDocument(EditDocumentActivity.scala:101) at pl.lantkowiak.sdm.activities.EditDocumentActivity.onOptionsItemSelected(EditDocumentActivity.scala:45) at android.app.Activity.onMenuItemSelected(Activity.java:2566) at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:404) at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:167) at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100) at android.support.v7.app.AppCompatDelegateImplV7.onMenuItemSelected(AppCompatDelegateImplV7.java:646) at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811) at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152) at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958) at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948) at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:618) at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:139) at android.view.View.performClick(View.java:4209) at android.view.View$PerformClick.run(View.java:17431) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:153) at android.app.ActivityThread.main(ActivityThread.java:5297) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) at dalvik.system.NativeStart.main(Native Method) Caused by: java.sql.SQLException: Cannot update class pl.lantkowiak.sdm.core.entity.DocumentFile because it doesn't have an id field at com.j256.ormlite.stmt.mapped.MappedUpdate.build(MappedUpdate.java:33) at com.j256.ormlite.stmt.StatementExecutor.update(StatementExecutor.java:402) at com.j256.ormlite.dao.BaseDaoImpl.update(BaseDaoImpl.java:350) at com.j256.ormlite.dao.RuntimeExceptionDao.update(RuntimeExceptionDao.java:261) at pl.lantkowiak.sdm.activities.EditDocumentActivity$$anonfun$updateFiles$2.apply(EditDocumentActivity.scala:134) at pl.lantkowiak.sdm.activities.EditDocumentActivity$$anonfun$updateFiles$2.apply(EditDocumentActivity.scala:130) at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59) at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48) at pl.lantkowiak.sdm.activities.EditDocumentActivity.updateFiles(EditDocumentActivity.scala:130) at pl.lantkowiak.sdm.activities.EditDocumentActivity.updateDocument(EditDocumentActivity.scala:101) at pl.lantkowiak.sdm.activities.EditDocumentActivity.onOptionsItemSelected(EditDocumentActivity.scala:45) at android.app.Activity.onMenuItemSelected(Activity.java:2566) at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:404) at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:167) at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100) at android.support.v7.app.AppCompatDelegateImplV7.onMenuItemSelected(AppCompatDelegateImplV7.java:646) at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811) at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152) at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958) at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948) at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:618) at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:139) at android.view.View.performClick(View.java:4209) at android.view.View$PerformClick.run(View.java:17431) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:153) at android.app.ActivityThread.main(ActivityThread.java:5297) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) at dalvik.system.NativeStart.main(Native Method)

Błąd sugeruje, iż encja ta nie posiada pola id. Sama encja wyglądała tak:

@DatabaseTable(tableName = "documentFiles") class DocumentFile { @DatabaseField(generatedId = true) var id: Int = _ @DatabaseField(canBeNull = false) var createDate: Date = _ @DatabaseField(canBeNull = false) var filename: String = _ @DatabaseField(canBeNull = false) var extension: String = _ @DatabaseField(canBeNull = false) var mime: String = _ @DatabaseField(canBeNull = false) var description: String = _ @DatabaseField(foreign = true, canBeNull = false) var document: Document = _ }

Encja oczywiście zawierała pole id, a sam zapis encji do bazy danych odbył się bez problemu.

Zanim przejdę do mojego rozwiązania to chciałbym odnieść się do znaku _, który występował przy kazdym polu, np:

@DatabaseField(generatedId = true) var id: Int = _

Idąc za dokumentacją języka:

A variable definition var x: T = _ can appear only as a member of a template. It introduces a mutable field with type T and a default initial value. The default value depends on the type T as follows: 0 if T is Int or one of its subrange types, 0L if T is Long, 0.0f if T is Float, 0.0d if T is Double, false if T is Boolean, () if T is Unit, null for all other types T .

Czyli w przypadku pola id powinno do niego zostać przypisane domyślnie 0.

Wracając do mojego rozwiązania problemu. Jedyną zmianą, którą zrobiłem w moim kodzie to poniższa modyfikacja.

@DatabaseField(generatedId = true) var id: Int = 0

Jak widać bezpośrednie przypisanie 0 do pola id pomogło z rozwiązaniem problemu.

Idź do oryginalnego materiału