yahoo / squidb

SquiDB is a SQLite database library for Android and iOS
https://github.com/yahoo/squidb/wiki
Apache License 2.0
1.31k stars 132 forks source link

database records not being saved #230

Closed mhadad closed 8 years ago

mhadad commented 8 years ago

Hi,

I'm not being able to save records to db. even when i issue countAll(Model.class) after calling persist on the model instance I get 0 as as number of records (persist is called twice and i'm running the countAll after the first persist). whats wrong?

package .com.mh.model;

import android.content.Context;

import com.yahoo.squidb.android.AndroidOpenHelper;
import com.yahoo.squidb.data.ISQLiteDatabase;
import com.yahoo.squidb.data.ISQLiteOpenHelper;
import com.yahoo.squidb.data.SquidDatabase;
import com.yahoo.squidb.sql.Table;

public class ModelController extends SquidDatabase {
    Context mContext;
    public ModelController(Context context)
    {
        super();
        mContext = context;
    }

    @Override
    public String getName() {
        return "enduser_pets.db";
    }

    @Override
    protected int getVersion() {
        return 9;
    }

    @Override
    protected Table[] getTables() {
        return new Table[]{
               Model.TABLE
        };
    }

    @Override
    protected boolean onUpgrade(ISQLiteDatabase db, int oldVersion, int newVersion) {
        mContext.deleteDatabase(getName());
        return false;
    }

    @Override
    protected ISQLiteOpenHelper createOpenHelper(String databaseName, OpenHelperDelegate delegate, int version) {
        return new AndroidOpenHelper(mContext, getName(), delegate, getVersion());
    }
}

ModelControler mController = new ModelController(getApplicationContext()); ModelClass mclass = new ModelClass(); mclass.setTitle("Hi"); mController.persist(mclass);

sbosley commented 8 years ago

I can't say for sure if this is the cause of your specific problem or not, but your onUpgrade() method would definitely cause some major issues:

I'd recommend you check out the Implementing database upgrades wiki page and follow the guidelines there for your onUpgrade method. If that doesn't solve your issue we'll probably need more information.

mhadad commented 8 years ago

I modified the above mentioned changes, removed the mContext.deleteDatabase to recreate() and true as onUpgrade return value but still cant save data to the db...so what information is needed to be able to help me more? and thanks

sbosley commented 8 years ago

If you come join our gitter chat at https://gitter.im/yahoo/squidb we can help you debug -- I think this will be easier than a back-and-forth on this issue.

mhadad commented 8 years ago
@TableModelSpec(className = "ModelClass", tableName = "model")
class Model
{
@PrimaryKey
long model_id;
String title;
}

package com.mh.model;

import android.content.Context;

import com.yahoo.squidb.android.AndroidOpenHelper;
import com.yahoo.squidb.data.ISQLiteDatabase;
import com.yahoo.squidb.data.ISQLiteOpenHelper;
import com.yahoo.squidb.data.SquidDatabase;
import com.yahoo.squidb.sql.Table;

public class ModelController extends SquidDatabase {
    Context mContext;
     private static ModelController mModelController;
    public static ModelController createDb(Context context)
    {
        if(mModelController == null)
        {
            mModelController = new ModelController(context);
        }
        return mModelController;
    }

    private ModelController(Context context)
    {
        super();
        mContext = context;
    }

    @Override
    public String getName() {
        return "enduser_pets.db";
    }

    @Override
    protected int getVersion() {
        return 9;
    }

    @Override
    protected Table[] getTables() {
        return new Table[]{
               ModelClass.TABLE
        };
    }

    @Override
    protected boolean onUpgrade(ISQLiteDatabase db, int oldVersion, int newVersion) {
        mContext.deleteDatabase(getName());
        return false;
    }

    @Override
    protected ISQLiteOpenHelper createOpenHelper(String databaseName, OpenHelperDelegate delegate, int version) {
        return new AndroidOpenHelper(mContext, getName(), delegate, getVersion());
    }
}

My Model class and Model database

mhadad commented 8 years ago
package pets_user.mahmoudhaddad.com.mh.pets_end_user.model;

import android.content.Context;

import com.yahoo.squidb.android.AndroidOpenHelper;
import com.yahoo.squidb.data.ISQLiteDatabase;
import com.yahoo.squidb.data.ISQLiteOpenHelper;
import com.yahoo.squidb.data.SquidDatabase;
import com.yahoo.squidb.sql.Table;

/**
 * Created by mahmoudhadad on 8/23/16.
 */
public class ModelController extends SquidDatabase {
    Context mContext;
    private static ModelController mModelController;
    public static ModelController createDb(Context context)
    {
        if(mModelController == null)
        {
            mModelController = new ModelController(context);
        }
        return mModelController;
    }

    private ModelController(Context context)
    {
        super();
        mContext = context;
    }

    @Override
    public String getName() {
        return "enduser_pets.db";
    }

    @Override
    protected int getVersion() {
        return 11;
    }

    @Override
    protected Table[] getTables() {
        return new Table[]{
                BusinessDetailModel.TABLE,
                PetKindModel.TABLE,
                ServiceModel.TABLE,
                ServiceDetailModel.TABLE,
                ProductModel.TABLE,
                ProductDetailModel.TABLE,
                BoardingServiceModel.TABLE,
                BoardingServicePetModel.TABLE,
                GroomingServiceModel.TABLE,
                GroomingServicePetModel.TABLE,
                ImportExportServiceModel.TABLE,
                ImportExportServicePetModel.TABLE,
                BusinessModel.TABLE
        };
    }

    @Override
    protected boolean onUpgrade(ISQLiteDatabase db, int oldVersion, int newVersion) {
        recreate();
        return true;
    }

    @Override
    protected ISQLiteOpenHelper createOpenHelper(String databaseName, OpenHelperDelegate delegate, int version) {
        return new AndroidOpenHelper(mContext, getName(), delegate, getVersion());
    }

}
mhadad commented 8 years ago
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.3'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

android {
    compileSdkVersion 23
    buildToolsVersion "24.0.1"

    defaultConfig {
        applicationId "pets_user.mahmoudhaddad.com.mh.pets_end_user"
        minSdkVersion 23
        targetSdkVersion 23
        multiDexEnabled = true
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:support-v4:23.4.0'
    compile 'com.android.support:design:23.4.0'
    compile 'com.yahoo.squidb:squidb:3.1.2'
    compile 'com.yahoo.squidb:squidb-annotations:3.1.2'
    compile 'com.yahoo.squidb:squidb-android:3.1.2' // For Android projects only
    apt 'com.yahoo.squidb:squidb-processor:3.1.2'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
}
mhadad commented 8 years ago

The calling method

for(int i =0 ; i < jsonArr.length; i++)
{
ModelClass mclass = new ModelClass();
mclass.setTitle("hi");
mController.persist(mclass);
}
mhadad commented 8 years ago

I'm only getting this warning ClassLoader referenced unknown path: /data/app/pets_user.mahmoudhaddad.com.mh.pets_end_user-2/lib/arm64

mhadad commented 8 years ago

Caused by: android.database.sqlite.SQLiteException: no such column: service.id (code 1): , while compiling: SELECT service.id AS id, service.serviceId AS serviceId, service.parentServiceId AS parentServiceId, service.nameAr AS nameAr, service.nameEn AS nameEn, service.serviceType AS serviceType, service.isActive AS isActive, service.isPublished AS isPublished, service.price AS price, service.businessId AS businessId FROM service WHERE (service.serviceType=?) LIMIT 10

mhadad commented 8 years ago

model spec

package pets_user.mahmoudhaddad.com.mh.pets_end_user.model;

import com.yahoo.squidb.annotations.TableModelSpec;

/**
 * Created by mahmoudhadad on 8/29/16.
 */
@TableModelSpec(className = "ServiceModel", tableName = "service")
public class Service {
    int id;
    long service_id;
    int parent_service_id = 0;
    String name_En = "", service_type = "";
    boolean isActive = false, isPublished = false;
}
mhadad commented 8 years ago

Fixed. It was a build tools issue. removed the @PrimaryKey annotations and renamed fields to not have a trailing classname_id names and it worked..Thanks for your help

sbosley commented 8 years ago

@mhadad I had a realization about a possible cause of your issue, just wanted to post it here so you saw it and were aware of the behavior. When you said it started working when you removed the @PrimaryKey annotations, I had a suspicion that perhaps the problem was that you were setting an integer primary key column to some value before calling persist(). SquiDB uses the SQLite rowid column as bookkeeping to determine whether or not a row "exists" when deciding on persist() logic. SQLite treats any column that is an integer primary key as an alias to the rowid, so when you declare a column as an integer or long and tag it with @PrimaryKey, SquiDB will use it for this bookkeeping instead. If such a column is set to a non-zero value before calling persist(), the persist method will attempt to do an update on that rowid, rather than an insert -- but if that row doesn't exist yet, the update will of course fail and persist will return false.

You never posted a full example of your persist code using the actual model class you were using so I can't say for sure, but if you had an integer primary key column and were setting it to a value before calling persist, that would be a very likely cause of the behavior you were seeing. Hope it helps.