ahmetb / orman

lightweight and minimalist ORM for Java/Android. works with SQLite & MySQL. (not actively maintained)
Other
249 stars 47 forks source link

Model entity update bug #50

Open lhanusiak opened 11 years ago

lhanusiak commented 11 years ago

When I execute update on model instance my application throws following exception:

java.lang.NullPointerException at org.orman.mapper.Model.prepareUpdateQuery(Model.java:197) at org.orman.mapper.Model.update(Model.java:162)

In my entity I use text field with as primary key which I manually fill before storing into database. Since method prepareUpdateQuery requires autoIncrement field it fails with NPE.

@Entity(table = "sui") public class SUI extends Model { @PrimaryKey private String id;

... }

In my opinion prepareUpdateQuery should check against @PrimaryKey annotation instead of autoincrement value.

ahmetb commented 11 years ago

Hi, @lhanusiak can you please share all fields in SUI class and your .update() code? Thanks.

fairchild88 commented 10 years ago

Hi @ahmetalpbalkan

I encounter this problem too. And after I change type of PrimaryKey to int, update works well. My Model class only have one PrimaryKey, and some String member and no relationship with else model.

fairchild88 commented 10 years ago

Hi @lhanusiak have you fixed this problem? And I agree with your opinion, Model.getEntityId(), should change to check primary key.

lhanusiak commented 10 years ago

To work around the problem I added @PrimaryKey(autoIncrement = true) id field and then created my text identifier field with @Index(unique=true). In my application I don really care about PK and only use indexed identifier.
Code sample that I use in my application:

@Entity(table = "sui") public class SUI extends Model {

@PrimaryKey(autoIncrement = true) private int id;

@Index(unique = true) private String identifier;

....

}

I aware that this approach is very naive but I hope that it will be helpful to you.

ahmetb commented 10 years ago

Hmm, I don't remember if auto increment is compulsory or not. Either way it should not throw NPE.

After defining your Model, which operation fails, can you please share the full stack trace? Thanks.

fairchild88 commented 10 years ago

stack trace show below: 01-02 15:14:23.957: E/AndroidRuntime(6435): Caused by: java.lang.NullPointerException 01-02 15:14:23.957: E/AndroidRuntime(6435): at org.orman.mapper.Model.prepareUpdateQuery(Model.java:198) 01-02 15:14:23.957: E/AndroidRuntime(6435): at org.orman.mapper.Model.update(Model.java:162) 01-02 15:14:23.957: E/AndroidRuntime(6435): at com.helowd.ormdemo.LoginActivity.onCreate(LoginActivity.java:54)

And extended Model User define like this

@Entity public class User extends Model { @PrimaryKey public String userid; ... }

Call like this:

User user = User.hasLoginedUser(); if(user != null) { user.member = "xxx"; user.update(); }

Bug exist in getAutoIncrementField

In this prepareUpdateQuery function(and other function like insert(), prepareDeleteQuery()), it calls getAutoIncrementField(), and return null. So not every entity contains auto increment field right? such as User model I define here, only contain one String member as Primary Key.

lhanusiak commented 10 years ago

Sample update code used in every case:

SUI sui = new SUI(); sui.setIdentifier("123412412342"); sui.setText("AAA"); sui.insert();

sui.setText("AAABBB"); sui.update();

Case 1: Using PK annotation on text field

@Entity(table = "sui") public class SUI extends Model { @PrimaryKey private String id;

... }

No error during initialization and insert but update fails every time.

Full stack trace: java.lang.NullPointerException at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4200) at android.app.ActivityThread.access$1400(ActivityThread.java:134) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) 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:1007) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) at dalvik.system.NativeStart.main(Native Method)

Caused by: java.lang.NullPointerException at org.orman.mapper.Model.prepareUpdateQuery(Model.java:197) at org.orman.mapper.Model.update(Model.java:162) at pl.com.mcg.hermes.android.convoys.HermesApplication.onCreate(HermesApplication.java:87) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1014) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4197)
... 10 more java.lang.NullPointerException
at org.orman.mapper.Model.prepareUpdateQuery(Model.java:197) at org.orman.mapper.Model.update(Model.java:162) at pl.com.mcg.hermes.android.convoys.HermesApplication.onCreate(HermesApplication.java:87) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1014) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4197) at android.app.ActivityThread.access$1400(ActivityThread.java:134) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) 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:1007) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) at dalvik.system.NativeStart.main(Native Method)

Case 2: Using SUI without auto increment PK field causes errors during database initialization phase

@Entity(table = "sui") public class SUI extends Model {

@NotNull @Index(unique = true) private String identifier;

...

}

Full stack trace: org.orman.dbms.exception.QueryExecutionException: Query execution error: SQLiteAndroid error:android.database.sqlite.SQLiteConstraintException: column identifier is not unique (code 19) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4200) at android.app.ActivityThread.access$1400(ActivityThread.java:134) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) 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:1007) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) at dalvik.system.NativeStart.main(Native Method)

Caused by: org.orman.dbms.exception.QueryExecutionException: Query execution error: SQLiteAndroid error:android.database.sqlite.SQLiteConstraintException: column identifier is not unique (code 19) at org.orman.dbms.sqliteandroid.QueryExecutionContainerImpl.throwError(QueryExecutionContainerImpl.java:30) at org.orman.dbms.sqliteandroid.QueryExecutionContainerImpl.executeOnly(QueryExecutionContainerImpl.java:41) at org.orman.mapper.Model.insert(Model.java:86) at pl.com.mcg.hermes.android.convoys.HermesApplication.onCreate(HermesApplication.java:84) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1014) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4197)

... 10 more org.orman.dbms.exception.QueryExecutionException: Query execution error: SQLiteAndroid error:android.database.sqlite.SQLiteConstraintException: column identifier is not unique (code 19) at org.orman.dbms.sqliteandroid.QueryExecutionContainerImpl.throwError(QueryExecutionContainerImpl.java:30) at org.orman.dbms.sqliteandroid.QueryExecutionContainerImpl.executeOnly(QueryExecutionContainerImpl.java:41) at org.orman.mapper.Model.insert(Model.java:86) at pl.com.mcg.hermes.android.convoys.HermesApplication.onCreate(HermesApplication.java:84) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1014) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4197) at android.app.ActivityThread.access$1400(ActivityThread.java:134) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) 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:1007) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) at dalvik.system.NativeStart.main(Native Method)

Case 3: @Entity(table = "sui") public class SUI extends Model {

@PrimaryKey(autoIncrement = true) private int id;

@NotNull @Index(unique = true) private String identifier;

... }

Causes no error during both initialization and insert/update operations.

fernandovarella commented 9 years ago

I'm having the same problem. Update fails because line 150 of Model.java looks for the AutoIncrement field:

var3.where(C.eq(this.getEntity().getAutoIncrementField().getGeneratedName(), this.__persistencyId));

my Entity has a Non-autoincrement String primary key, thus, the update fails