androidsqlitegreendaogreendao-generator

GreenDao IndsertOrReplaceInTx only insert last item of list


I have some POJOS and create some tables for them. All of them work well which means I can insert them and load them ... except this one:

My Brand list contains 6 elements and I am really sure they are different(put break point and saw them) but when I am going to insert them in DB by greenDao only last element is inserted. My table is empty and this statement suppose to fill it.

Codes:

public class SingletonDatabase {

    private static SingletonDatabase mInstance;
    private DaoMaster.OpenHelper mHelper;
    private DaoSession mDaoSessionForUI;
    private DaoMaster mDaoMaster;
    private static Context mCtx;

    private SingletonDatabase(Context context) {
        mCtx = context;
        setupDb();
    }

    public static synchronized SingletonDatabase getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new SingletonDatabase(context);
        }
        return mInstance;
    }

    private void setupDb() {
        mHelper = new DaoMaster.OpenHelper(
                mCtx.getApplicationContext(), "mydb", null) {

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion,
                    int newVersion) {
                // Handle upgrade
            }
        };

        SQLiteDatabase db = mHelper.getWritableDatabase();
        mDaoMaster = new DaoMaster(db);
        mDaoSessionForUI = mDaoMaster.newSession();


    }

    public DaoSession getDaoSessionForUI() {
        return mDaoSessionForUI;

    }

    public DaoSession getDaoSeesion(){

        return mDaoMaster.newSession();
    }

}

The generated Brand code:

 * Entity mapped to table BRAND.
 */
public class Brand {

    private long tableId;
    private String id;
    private String name;
    private String publicImage;
    private String description;
    private String lastDownloadedTime;

    public Brand() {
    }

    public Brand(long tableId) {
        this.tableId = tableId;
    }

    public Brand(long tableId, String id, String name, String publicImage, String description, String lastDownloadedTime) {
        this.tableId = tableId;
        this.id = id;
        this.name = name;
        this.publicImage = publicImage;
        this.description = description;
        this.lastDownloadedTime = lastDownloadedTime;
    }

    public long getTableId() {
        return tableId;
    }

    public void setTableId(long tableId) {
        this.tableId = tableId;
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPublicImage() {
        return publicImage;
    }

    public void setPublicImage(String publicImage) {
        this.publicImage = publicImage;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getLastDownloadedTime() {
        return lastDownloadedTime;
    }

    public void setLastDownloadedTime(String lastDownloadedTime) {
        this.lastDownloadedTime = lastDownloadedTime;
    }

}

The code for creating schema:

public class DaoGen {

    public static void main(String[] args) throws Exception {

        Schema schema = new Schema(1, "com.mmlooloo");

        Entity brandList = addBrand(schema);



        File f = new File("src-gen");
        f.mkdir();

        new DaoGenerator().generateAll(schema,f.getAbsolutePath());
    }

    private static Entity addBrand(Schema schema) {

        Entity brand = schema.addEntity("Brand");
        brand.addLongProperty("tableId").notNull().primaryKey().autoincrement();
        brand.addStringProperty("id");
        brand.addStringProperty("name");
        brand.addStringProperty("publicImage");
        brand.addStringProperty("description");
        brand.addStringProperty("lastDownloadedTime");
        return brand; 

    }

}

and finally how I insert them:

public class BrandDownloadService extends IntentService {
public BrandDownloadService() {
    super("BrandDownloadService");

}
@Override
protected void onHandleIntent(Intent intent) {
    ....
    BrandDao brandDao = SingletonDatabase.getInstance(this).getDaoSeesion().getBrandDao();
    brandDao.insertOrReplaceInTx(brandList,true);

}

I set break point and check my brandlist and it has 6 elements.

Any help, work around, debug tips ... I really do not know what the problem is.

Many thanks!!

EDIT:

I have created very very simple (really simple believe me :-)) test project that reads json from file, parse it to list and insert it to db at this and the problem exists. Can anyone tell me what is my mistake? many many thanks :-).


Solution

  • Probably your 6 Brand-Items share the same tableId. Thus greendao thinks this is one item (identified by the primary key) and replaces the first with the second, the second with the third and so on...

    If you used notNull().primaryKey().autoincrement()

    I once had the same problem and "fixed" it by changing the dao-template that is used for codegeneration in the dao-generator project.

    Perhaps it will also work if you are not using notNull() on the primarykey property.

    UPDATE

    I had a look at greendao again:

    In greendao-generator, file src-template/dao.ftl you can find the following lines:

    protected void bindValues(SQLiteStatement stmt, ${entity.className} entity) {
        stmt.clearBindings();
    <#list entity.properties as property>
    <#if property.notNull || entity.protobuf>
    <#if entity.protobuf>
        if(entity.has${property.propertyName?cap_first}()) {
    </#if>        stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, entity.get${property.propertyName?cap_first}()<#if
     property.propertyType == "Boolean"> ? 1l: 0l</#if><#if property.propertyType == "Date">.getTime()</#if>);
    

    This means, that if you are using notNull() on your autoincrement-property the corresponding variable will always be bound to insert or update statements. This results in always setting the value for your primary key manually and ignoring the autoincrement, since

    CREATE TABLE mytable ( id integer primary key autoincrement, details varchar(30));
    INSERT INTO mytable (id, details) VALUES (0, 'something');
    

    results in this db-row: 0 | 'something'.

    Hence it is a bug inside greendao! To solve this you can either not specify notNull on your primary-key column or you can modify the file dao.ftl (line 126ff):

    <#list entity.properties as property>
    <#if property.notNull || entity.protobuf>
    <#if entity.protobuf>
            if(entity.has${property.propertyName?cap_first}()) {
    </#if>
    <#if property.pkAutoincrement>
            if(entity.get${property.propertyName?cap_first}() != 0) {
    </#if>        stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, entity.get${property.propertyName?cap_first}()<#if
         property.propertyType == "Boolean"> ? 1l: 0l</#if><#if property.propertyType == "Date">.getTime()</#if>);
    <#if entity.protobuf || property.pkAutoincrement>
        }
    </#if>
    <#else> <#-- nullable, non-protobuff -->
        ${property.javaType} ${property.propertyName} = entity.get${property.propertyName?cap_first}();
        if (${property.propertyName} != null) {
    <#if property.pkAutoincrement>    if (${property.propertyName} != 0) {
        </#if>       stmt.bind${toBindType[property.propertyType]}(${property_index + 1}, ${property.propertyName}<#if property.propertyType == "Boolean"> ? 1l: 0l</#if><#if property.propertyType == "Date">.getTime()    </#if>);
    <#if property.pkAutoincrement>        }</#if>
        }
    </#if>
    

    This will cause greendao to NOT bind your autoincrement-primarykey value to your update or insert statements unless it is != 0 or null.

    Be careful with the second approach though: It is untested and therefore may as well have sideeffects on other parts of greendao!