I am using ORMlite database for the first time in my application. i have taken reference from a tutorial, but instead of doing all the things exactly same i am not able to resolve an error. My code is below:-
DatabaseHelper:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "qzeodemo.db";
private static final int DATABASE_VERSION = 1;
private Dao<ModifierDetails, Integer> itemsDao;
private Dao<ItemDetails, Integer> modifiersDao;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION, R.raw.ormlite_config);
}
#Override
public void onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource) {
try {
// Create tables. This onCreate() method will be invoked only once of the application life time i.e. the first time when the application starts.
TableUtils.createTable(connectionSource,ItemDetails.class);
TableUtils.createTable(connectionSource,ModifierDetails.class);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Unable to create datbases", e);
}
}
#Override
public void onUpgrade(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource, int oldVer, int newVer) {
try {
// In case of change in database of next version of application, please increase the value of DATABASE_VERSION variable, then this method will be invoked
//automatically. Developer needs to handle the upgrade logic here, i.e. create a new table or a new column to an existing table, take the backups of the
// existing database etc.
TableUtils.dropTable(connectionSource, ItemDetails.class, true);
TableUtils.dropTable(connectionSource, ModifierDetails.class, true);
onCreate(sqliteDatabase, connectionSource);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Unable to upgrade database from version " + oldVer + " to new "
+ newVer, e);
}
}
// Create the getDao methods of all database tables to access those from android code.
// Insert, delete, read, update everything will be happened through DAOs
public Dao<ItemDetails,Integer> getItemDao() throws SQLException {
if (itemsDao == null) {
itemsDao = getDao(ItemDetails.class);
}
return itemsDao;
}
public Dao<ModifierDetails, Integer> getMofifierDao() throws SQLException {
if (modifiersDao == null) {
modifiersDao = getDao(ModifierDetails.class);
}
return modifiersDao;
}
}
The line where i am using modifiersDao = getDao(ModifierDetails.class); is giving error
Error:(76, 30) error: invalid inferred types for D; inferred type does not conform to declared bound(s)
inferred: Dao
bound(s): Dao
where D,T are type-variables:
D extends Dao declared in method getDao(Class)
T extends Object declared in method getDao(Class)
Please help :(
Your declaration is wrong above:
private Dao< ItemDetails, Integer > modifiersDao;
but getMofifierDao() returns Dao< ModifierDetails, Integer>
Related
I'm trying to create a backup of my sqlite database and I want to flush the content of the WAL file in the db first.
Here is my SQLiteOpenHelper:
public class MyDBHelper extends SQLiteOpenHelper {
private Context mContext;
private static MyDBHelper mInstance = null;
private MyDBHelper(final Context context, String databaseName) {
super(new MYDB(context), databaseName, null, DATABASE_VERSION);
this.mContext = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public static MyDBHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new MyDBHelper(context, DATABASE_NAME);
}
return mInstance;
}
private void closeDataBase(Context context) {
getInstance(context).close();
}
}
Now, my understanding is that after a checkpoint is completed, the mydb.db-wal file should be empty. Is that correct?
Here is what I've tried so far:
1.
public Completable flushWalInDB() {
return Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
getInstance(mContext).getReadableDatabase().rawQuery("pragma wal_checkpoint;", null);
}
});
}
This doesn't throw an error but doesn't seem to do anything. After running this, I physically checked my mydb.db-wal file and had the same size. I also checked the db on the device and nothing was added in the database
After some digging around I found this
[https://stackoverflow.com/a/30278485/2610933][1]
and tried this:
2.
public Completable flushWalInDB() {
return Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
getInstance(mContext).getReadableDatabase().execSQL("pragma wal_checkpoint;");
}
});
}
When running this it throws an error:
unknown error (code 0): Queries can be performed using SQLiteDatabase query or rawQuery methods only.
And based on this answer [https://stackoverflow.com/a/19574341/2610933][1] , I also tried to VACUUM the DB but nothing seems to happen.
public Completable vacuumDb() {
return Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
getInstance(mContext).getReadableDatabase().execSQL("VACUUM");
}
});
}
}
Whats is the correct way of flushing the WAL file in the DB before creating a backup?
Thank you.
PRAGMA wal_checkpoint(2) does copy all data from the WAL into the actual database file, but it does not remove the -wal file, and any concurrent connections can make new changes right afterwards.
If you want to be really sure that there is no WAL to interfere with your backup, run PRAGMA journal_mode = DELETE. (You can switch it back afterwards.)
To manually add checkpont use PRAGMA wal_checkpoint, after searching for 2 hours following code worked for me -:
SQLiteDatabase db = this.getWritableDatabase();
String query = "PRAGMA wal_checkpoint(full)";
Cursor cursor = db.rawQuery(query, null);
if (cursor != null && cursor.moveToFirst()) {
int a = cursor.getInt(0);
int b = cursor.getInt(1);
int c = cursor.getInt(2);
}
if (cursor != null) {
cursor.close();
}
I am trying to create a DatabaseConfigUtil which extends OrmLiteConfigUtil in Android Studio. I followed the steps specified here but since it mentions steps to follow in Eclipse, I got lost in the middle.
public class DatabaseConfigUtility extends OrmLiteConfigUtil {
public static void main(String[] args) {
try {
writeConfigFile("ormlite_config.txt");
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I tried to Edit configuration for the class still it throws an error because I have defined the path to the config file in my DatabaseHelper class
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "notes.db";
private static final int DATABASE_VERSION = 1;
private Dao<Note, Integer> noteDao = null;
private RuntimeExceptionDao<Note, Integer> noteRunTimeDao = null;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION, R.raw.ormlite_config);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
try {
// TableUtils.clearTable will create Table having attribute equals to Note class
TableUtils.createTable(connectionSource, Note.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int i, int i2) {
try {
// first drop the table and then create the table again.
TableUtils.dropTable(connectionSource, Note.class, true);
onCreate(sqLiteDatabase, connectionSource);
} catch (SQLException e) {
e.printStackTrace();
}
}
public Dao<Note, Integer> getNoteDao() throws SQLException {
if (noteDao == null) {
noteDao = getDao(Note.class);
}
return noteDao;
}
public RuntimeExceptionDao<Note, Integer> getNoteRunTimeDao() {
if (noteRunTimeDao == null) {
noteRunTimeDao = getRuntimeExceptionDao(Note.class);
}
return noteRunTimeDao;
}
}
The gradle execution fails and throws this error which is because I have declared the path to config file and it does not exist.
Error:Gradle: Execution failed for task ':app:compileDebugJava'.
Compilation failed; see the compiler error output for details.
C:\Users\Pavitra\Documents\AndroidStudio\ORMLiteDemo\app\src\main\java\orm\entities\DatabaseHelper.java
Error:(24, 64) Gradle: error: cannot find symbol variable raw
In order to create ormlite_config.txt file, I have to run the DatabaseConfigUtil class.
How to run the DatabaseConfigUtil to generate the ormlite_config.txt file?
Any help or advice is much appreciated.
Thanks in advance.
I'm trying to get a pattern that doesn't fail for a multithreaded access to my sqlite database. Also, what is driving me nuts is that I can't reproduce the issue.
I have an app which uses a DB, but also Android Accounts and Android sync to sync my app's data. My guess is that when the two happen a the same time, it crashes. I'm getting a lot of errors like:
* android.database.sqlite.SQLiteDatabaseLockedException: database is locked
* android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
* android.database.sqlite.SQLiteDatabaseLockedException: error code 5: database is locked
* android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
* android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 778)
* android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/net.bicou.redmine/databases/redmine.db' to 'en_US'. \n Caused by: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
Maybe not all of them are related to the same root cause, however I'm kind of lost.
What I have is:
an abstract base class, DbAdapter, that is extended by subclasses which want to manage a single table
a class that manages the SQLite database, called DbManager, which contains a Lock
Right now the users have a version of the DbManager that is not a singleton. I'm planning to make DbManager a singleton, so that all threads share the same object. This shouldn't be a problem, because as far as I have understood/seen, the background sync and app share the same process.
Here are the classes (only the relevant parts):
public abstract class DbAdapter {
Context mContext;
protected DbManager mDbManager;
SQLiteDatabase mDb;
public static final String KEY_ROWID = "_id";
public DbAdapter(final Context ctx) {
mContext = ctx;
}
public DbAdapter(final DbAdapter other) {
mContext = other.mContext;
mDb = other.mDb;
mDbManager = other.mDbManager; // removed with singleton version
}
public synchronized DbAdapter open() throws SQLException {
if (mDb != null) {
return this;
}
mDbManager = new DbManager(mContext); // currently in production
mDbManager = DbManager.instance(mContext); // currently investigating this singleton solution
try {
mDb = mDbManager.getWritableDatabase();
} catch (final SQLException e) {
L.e("Unable to open DB, trying again in 1 second", e);
try {
Thread.sleep(1000);
} catch (final InterruptedException e1) {
L.e("Could not wait 1 second " + e1);
}
mDb = mDbManager.getWritableDatabase();// This may crash
}
return this;
}
public synchronized void close() {
mDbManager.close();
mDbManager = null;
mDb = null;
}
}
A class that needs to handle a database table will extend DbAdapter, and implement methods such as select, insert, delete, etc.
Here's the DB manager:
public class DbManager extends SQLiteOpenHelper {
private static final String DB_FILE = "db";
private static final int DB_VERSION = 15;
Context mContext;
Lock mLock = new ReentrantLock();
// Currently in prod
public DbManager(final Context context) {
super(context, DB_FILE, null, DB_VERSION);
mContext = context;
}
// singleton version will make this constructor private and add:
private static DbManager mInstance;
public static synchronized DbManager instance(Context context) {
if (instance == null) {
instance = new DbManager(context);
}
return instance;
}
#Override
public SQLiteDatabase getWritableDatabase() {
mLock.lock();
return super.getWritableDatabase();
}
#Override
public void close() {
super.close();
mLock.unlock();
}
#Override
public void onCreate(final SQLiteDatabase db) {
// ...
}
#Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
// ...
}
private void createTables(final SQLiteDatabase db, final String[] statements) {
for (final String sql : statements) {
try {
db.execSQL(sql);
} catch (final Exception e) {
L.e("Unable to create table: " + sql, e);
}
}
}
}
OK, now, the questions.
Is my lock properly implemented? I'm really new to this, I don't know if the ReentrantLock is a good choice, and if I'm locking/unlocking at the right moment
Are my synchronized method properly implemented? I mean, I have placed the synchronized keyword around methods that I don't want interrupted by concurrent threads. Is this right? Can you advice on my synchronized use?
How can I reproduce the issue? I have created a test that uses 3 threads that make concurrent read/write access to the DB, and use some Thread.sleep to ensure that the db open/close from each thread overlap, but it doesn't crash. This is really bugging me, I don't think there is a lot of people that have the issue, so I don't know how to reproduce.
Is my DbAdapter + DbManager technical choice a good idea? Is there a better pattern?
Is it a good idea to make DbManager a singleton?
For multiple threads accessing, it is advisable to use the singleton pattern.
Such a way, successive calls to the same database will be seamlessly serialised.
However, it's not impossible to have some NullPointerExceptions on inserts. So, to expand your "Thread.sleep" logic, you could use this code:
#Override
public SQLiteDatabase getWritableDatabase() {
while (true) {
try {
return super.getWritableDatabase();
} catch (SQLiteDatabaseLockedException e) {
System.err.println(e);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.err.println(e);
}
}
}
I am using ormlite.android.4.31.jar
I have typical DatabaseHelper
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "realestate.db";
private static final int DATABASE_VERSION = 1;
private Dao<TabKraj, Integer> krajDao;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource) {
try {
TableUtils.createTable(connectionSource, TabKraj.class);
initData();
} catch (Exception e) {
Log.e(DatabaseHelper.class.getName(), "Unable to create datbases", e);
}
}
#Override
public void onUpgrade(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource, int oldVer, int newVer) {
try {
TableUtils.dropTable(connectionSource, TabKraj.class, true);
onCreate(sqliteDatabase, connectionSource);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Unable to upgrade database from version " + oldVer + " to new " + newVer, e);
}
}
public Dao<TabKraj, Integer> getKrajDao() throws SQLException{
if (krajDao == null) {
krajDao = getDao(TabKraj.class);
}
return krajDao;
}
private void initData(){
Log.d(Constants.DEBUG_TAG, "data initiating");
TabKraj k1 = new TabKraj();
TabKraj k2 = new TabKraj();
k1.setNazov("Kosicky kraj");
k1.setId(1);
try {
getKrajDao().create(k1);
} catch (SQLException e) {
Log.e(Constants.DEBUG_TAG, "Data initialing ERROR");
}
}
}
app is uninstalled, data cleared ...
I am running app in debug mode from eclipse, constructor of DatabaseHleper is called but onCreate() is not called.
Where could the problem be?
As #k-mera said:
Database file will be created only if you did some operations in Database like "insert".
Although you say the data is cleared, I suspect that Android thinks it has not. To completely remove the data, I would remove the application and re-install it.
Since your onUpgrade calls onCreate you could also increase the DATABASE_VERSION value which will cause the data to be dropped and re-created.
I am getting NullPointerException in the marked in the code.
The code typically reads a text file in raw folder in the project and inserts the contents in the table of the database. The text file in the raw folder contains a list of english words, for spell checking purpose. Could anyone help me regarding this matter.
public class WordsDB
{
private static final String FTS_WORD_DB="FTS_WORD_DB";
private static final String WORD="WORD";
private static final String FTS_WORD_DB_CREATE="CREATE VIRTUAL TABLE "+FTS_WORD_DB+" USING ft3 ("+WORD+");";
private static final String WORD_DATABASE="WORD_DATABSE";
private static final int DATABSE_VERSION=1;
private WordsDBLoadHelper helper;
public static SQLiteDatabase wordDb;
public WordsDB(Context context)
{
helper=new WordsDBLoadHelper(context);
}
public void load()
{
helper.loadWordDb();
}
public class WordsDBLoadHelper extends SQLiteOpenHelper
{
public WordsDBLoadHelper(Context context)
{
super(context, WORD_DATABASE, null, DATABSE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
wordDb=db;
wordDb.execSQL(FTS_WORD_DB_CREATE);
}
public void loadWordDb()
{
Resources resource=SearchDict.context.getResources();
InputStream is=resource.openRawResource(R.raw.wordlist);
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String line;
try
{
while((line=br.readLine())!=null)
{
addWord(line.trim());
}
}
catch (Exception e)
{
Log.e(null, e.getStackTrace().toString(), e);
}
}
public void addWord(String line)
{
try
{
ContentValues values=new ContentValues();
values.put(WORD, line);
wordDb.insert(FTS_WORD_DB, null, values);
}
catch(Exception e)
{
Log.e(null, e.getStackTrace().toString(), e);
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
}
}
}
Is there any faster method to create table and insert values into it. The above procedure takes about more than a hour to insert values in the database because the text file contains more than 3 lakh words.
Is it possible to create the database once and store it permanently so that it is possible to retrieve values without recreating the database again and again when the project runs.
In Sqlite inserts are generally quite fast, but commits are slow. You're not using a transaction so after each insert sqlite does a commit.
wordDB.startTransaction();
try {
/*while loop*/
wordDB.setTransactionSuccessful();
} finally {
db.endTransaction();
}