проблемы с моим SQLiteOpenHelper

1
package com.owen.quartergames.dao;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.widget.Toast;

import com.owen.quartergames.R;
import com.owen.quartergames.domain.LogEntry;

public class SqlLiteFishLoggerDao extends SQLiteOpenHelper implements
        FishLoggerDao {

    private static final String DB_NAME = "fishingLog";

    private static final String TABLE_NAME = "LogEntries";

    private static final String DELETE_LOG_ENTRY_SQL = "DELETE FROM LogEntries WHERE _id = ?;";

    private static final String FIND_LOG_ENTRY_SQL = "SELECT _id, Longitude, Latitude FROM LogEntries WHERE _id = ?";

    private static final String FIND_ALL_ENTRIES_SQL = "SELECT * FROM LogEntries";

    private static final String[] NO_ARGS = {};

    private Context context;

    private final SQLiteDatabase db = getWritableDatabase();

    public SqlLiteFishLoggerDao(Context context) {
        super(context, DB_NAME, null, 1);
        this.context = context;
    }

    @Override
    public void deleteLogEntry(String id) {
        id = "0";

        db.execSQL(DELETE_LOG_ENTRY_SQL, new Object[] { id });
        // int deleted = db.delete(TABLE_NAME, "_id = ?",
        // new String[] { id.trim() });
        // Log.i("fishlogger", String.format("Delete %d rows", deleted));
        db.close();
    }

    @Override
    public LogEntry findEntry(String id) {
        Cursor cursor = db.rawQuery(FIND_LOG_ENTRY_SQL, new String[] { id });
        if (!cursor.moveToFirst()) {
            return null;
        }

        LogEntry entry = new LogEntry();
        entry.setId(id);
        entry.setLatitude(cursor.getDouble(cursor.getColumnIndex("Latitude")));
        entry
                .setLongitude(cursor.getDouble(cursor
                        .getColumnIndex("Longitude")));
        cursor.close();
        db.close();
        return entry;

    }

    @Override
    public void insertLogEntry(LogEntry entry) {
        ContentValues values = new ContentValues();
        values.put("Latitude", entry.getLatitude());
        values.put("Longitude", entry.getLongitude());
        values.put("PictureURL", entry.getPictureUrl());
        values.put("SizeOrWeight", entry.getSizeOrWeight());
        values.put("CreateDate", entry.getEntryDate());
        values.put("Species", entry.getSpecies());
        db.insertOrThrow("LogEntries", null, values);
        db.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String s;
        try {
            Toast.makeText(context, "1", 2000).show();
            InputStream in = context.getResources().openRawResource(R.raw.sql);
            DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder();
            Document doc = builder.parse(in, null);
            NodeList statements = doc.getElementsByTagName("statement");
            for (int i = 0; i < statements.getLength(); i++) {
                s = statements.item(i).getChildNodes().item(0).getNodeValue();
                db.execSQL(s);
            }
        } catch (Throwable t) {
            Toast.makeText(context, t.toString(), 50000).show();
        }
        Log.e("DB", "DB Created");

    }

    @Override
    public List<LogEntry> findAllEntries() {

        List<LogEntry> entries = new ArrayList<LogEntry>();

        Cursor cursor = db.rawQuery(FIND_ALL_ENTRIES_SQL, NO_ARGS);

        int entryDateCol = cursor.getColumnIndex("CreateDate");
        int speciesCol = cursor.getColumnIndex("Species");
        int sizeCol = cursor.getColumnIndex("SizeOrWeight");
        int latCol = cursor.getColumnIndex("Latitude");

        if (cursor.moveToFirst()) {
            do {
                LogEntry entry = new LogEntry();
                entry.setEntryDate(cursor.getString(entryDateCol));
                entry.setSpecies(cursor.getString(speciesCol));
                entry.setSizeOrWeight(cursor.getString(sizeCol));
                entry.setLatitude(cursor.getDouble(latCol));

                if (entry.getSpecies() == null) {
                    entry.setSpecies("Not Entered");
                }

                if (entry.getSizeOrWeight() == null) {
                    entry.setSizeOrWeight("Not entered");
                }

                entries.add(entry);
            } while (cursor.moveToNext());
        }
        cursor.close();
        db.close();
        return entries;
    }

    @Override
    public void onUpgrade(SQLiteDatabase DB, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(getWritableDatabase());
    }
}

в основном удаление не работает, но я думаю, что проблемы возникают из метода findAllEntries(). причина, по которой я говорю, что это то, что я получаю "обнаруженные утечки" ошибки в log cat, говорящие, что db был создан, но никогда не закрывался. я на самом деле обыскал интернет и попросил друзей, которые закодировали, но не повезло в решении проблемы. все мои курсоры закрыты, и из того, что я могу сказать, так должно выглядеть как sqlliteopenhelper.

спасибо за любые ответы

Теги:

3 ответа

0
Лучший ответ

просто хотел следить. Я благодарю вас за вашу помощь. в конце концов, похоже, было несколько вопросов. Theres очень мало шансов, что вы, ребята, могли бы понять это на ур с тем, что я дал, и это потребовало меня навсегда, чтобы понять это.
в любом случае, что я сделал не так, плюс обновленный код:

  • Я не открывал и не закрывал БД для каждого метод (обнаруженные утечки)

  • Находка оказалась не _id в объект. и поэтому, когда мой список был заполнен, и сказал delete, он будет использовать Итератор id в отличие от реального database _id записи.

  • Мне нужно было позвонить .trim на мой идентификатор Поле

(оба 2 и 3, однако, не выдавали ошибок в logcat, он просто никогда не удалял, он вставил отлично, выберите * fine, но ничего не произошло при удалении)


package com.owen.quartergames.dao;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import com.owen.quartergames.R;
import com.owen.quartergames.domain.LogEntry;

public class SqlLiteFishLoggerDao extends SQLiteOpenHelper implements
        FishLoggerDao {

    private static final String DB_NAME = "fishingLog";

    private static final String TABLE_NAME = "LogEntries";

    private static final String DELETE_LOG_ENTRY_SQL = "DELETE FROM LogEntries WHERE _id = ?;";

    private static final String FIND_LOG_ENTRY_SQL = "SELECT _id, Longitude, Latitude FROM LogEntries WHERE _id = ?";

    private static final String FIND_ALL_ENTRIES_SQL = "SELECT * FROM LogEntries";

    private static final String[] NO_ARGS = {};

    private Context context;

    private SQLiteDatabase DB;

    public SqlLiteFishLoggerDao(Context context) {
        super(context, DB_NAME, null, 1);
        this.context = context;
    }

    @Override
    public void deleteLogEntry(String id) {
        DB = getWritableDatabase();
        DB.execSQL(DELETE_LOG_ENTRY_SQL, new Object[] { id });
        DB.close();
    }

    @Override
    public LogEntry findEntry(String id) {
        DB = getReadableDatabase();
        Cursor cursor = DB.rawQuery(FIND_LOG_ENTRY_SQL,
                new String[] { id });
        if (!cursor.moveToFirst()) {
            return null;
        }

        LogEntry entry = new LogEntry();
        entry.setId(id);
        entry.setLatitude(cursor.getDouble(cursor.getColumnIndex("Latitude")));
        entry
                .setLongitude(cursor.getDouble(cursor
                        .getColumnIndex("Longitude")));
        cursor.close();
        DB.close();
        return entry;

    }

    @Override
    public void insertLogEntry(LogEntry entry) {
        DB = getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("Latitude", entry.getLatitude());
        values.put("Longitude", entry.getLongitude());
        values.put("PictureURL", entry.getPictureUrl());
        values.put("SizeOrWeight", entry.getSizeOrWeight());
        values.put("CreateDate", entry.getEntryDate());
        values.put("Species", entry.getSpecies());
        DB.insertOrThrow("LogEntries", null, values);
        DB.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String s;
        try {
            InputStream in = context.getResources().openRawResource(R.raw.sql);
            DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder();
            Document doc = builder.parse(in, null);
            NodeList statements = doc.getElementsByTagName("statement");
            for (int i = 0; i < statements.getLength(); i++) {
                s = statements.item(i).getChildNodes().item(0).getNodeValue();
                db.execSQL(s);
            }
            Log.e("DB", "DB Created Successfully");
        } catch (Throwable t) {
            Log.e("DB error: ",t.toString());
        }
    }

    @Override
    public List<LogEntry> findAllEntries() {
        DB = getReadableDatabase();

        List<LogEntry> entries = new ArrayList<LogEntry>();

        Cursor cursor = DB.rawQuery(FIND_ALL_ENTRIES_SQL,
                NO_ARGS);

        int entryID = cursor.getColumnIndex("_id");
        int entryDateCol = cursor.getColumnIndex("CreateDate");
        int speciesCol = cursor.getColumnIndex("Species");
        int sizeCol = cursor.getColumnIndex("SizeOrWeight");
        int latCol = cursor.getColumnIndex("Latitude");

        if (cursor.moveToFirst()) {
            do {
                LogEntry entry = new LogEntry();
                entry.setId(cursor.getString(entryID));
                entry.setEntryDate(cursor.getString(entryDateCol));
                entry.setSpecies(cursor.getString(speciesCol));
                entry.setSizeOrWeight(cursor.getString(sizeCol));
                entry.setLatitude(cursor.getDouble(latCol));

                if (entry.getSpecies() == null) {
                    entry.setSpecies("Not Entered");
                }

                if (entry.getSizeOrWeight() == null) {
                    entry.setSizeOrWeight("Not entered");
                }

                entries.add(entry);
            } while (cursor.moveToNext());
        }
        cursor.close();
        DB.close();
        return entries;
    }

    @Override
    public void onUpgrade(SQLiteDatabase DB, int oldVersion, int newVersion) {
        DB = getWritableDatabase();
        DB.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(getWritableDatabase());
        DB.close();
    }
}
1

Ваш getReadableDatabase() открывает БД для чтения. Чтобы избежать утечек, вам необходимо закрыть его после завершения вашей работы.

final db = getReadableDatabase();
//do the things
db.close();

То же самое с getWritableDatabase().

  • 0
    Я настоятельно рекомендую хранить БД в переменной-члене, чтобы не вызывать метод получения каждый раз ...
  • 0
    Объясните пожалуйста? Я предполагаю, что нам нужно открывать-закрывать БД каждый раз, когда нам это нужно. Вы предлагаете оставить его открытым или я вас неправильно понял? getReadableDatabase() - это не просто геттер, он открывает или создает БД.
Показать ещё 4 комментария
0

Как указано в SQLiteOpenHelper.getWritableDatabase javadoc:

После успешного открытия база данных кэшируется, поэтому вы можете вызывать этот метод каждый раз, когда вам нужно писать в базу данных. (Обязательно вызовите функцию close(), когда вам больше не нужна база данных.)

  • 0
    выполняет ли вызов getwritabledatabase, если он вызывается снова после однократного закрытия. например, я вызываю его, чтобы найти все записи, затем закрываю его, а затем повторяю вызов для удаления записи. это должно открыть БД для правки редактирования?
  • 0
    Да, так и должно быть.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню