具有多个表的SQLite DB

时间:2019-12-01 00:39:11

标签: android sqlite

我一直看到有关如何将DBHelper与多个表一起使用的示例,但是它们都具有在DBHelper类而不是每个数据类中定义的主题数据和查询。这似乎是错误的,就像没有保留关注点分离一样。我可能会误解如何使用DBHelper。对于DBHelper来说,最好只拥有数据库的基础部分(例如Create),然后将各个数据库函数(例如“ Insert”)放在每个主题类(例如Book.insert,Author.insert等)中,然后再添加它们可以使用DBHelper。在DBHelper中结合书籍和作者的DB函数似乎是错误的。 有没有人有一个如何编码的例子,或者是为什么没有必要的解释?预先感谢!

1 个答案:

答案 0 :(得分:1)

  

有人能举例说明如何编码,还是可以解释为什么没有必要?

正如您所看到的示例,当它们起作用时,显然没有必要。

  • 实际上,当它归结为它时,不需要DBHelper,因为它可以方便地检查数据库是否存在,是否不创建数据库并调用onCreate,然后打开与数据库的连接(如果存在或不存在)存在。

将扩展SQliteOpenHelper(DBHelper)的一个类中的所有内容组合在一起,具有一点优势,即可以使用this.getWritableDatabase()检索SQLiteDatabase,在构造函数中设置在类级别声明的变量可以进一步简化事务;然后,您可以简单地引用变量。

可以进行合并的另一个原因是,由于SQLite是一个关系数据库,因此关系会使得分离变得过于复杂/混乱。在哪里放置用于处理tableA和tableB之间的关系的代码,然后在哪里放置用于tableA和tableC与tableB和tableC之间的关系的代码以及有关tableA,tableB和tableC的代码........ 。然后,如果您有通用代码或实用程序代码。

如果使用单独的类,则需要传递DBHelper实例或SQLite数据库实例。

当有多个开发人员,每个开发人员都可以处理整个较小的组件时,将使用单独的类。

这样,在SO组合中回答问题具有明显的优势。

拆分-示例

DBHelper.java

/**
 * DBHelper
 */
@SuppressWarnings("WeakerAccess")
class DBHelper extends SQLiteOpenHelper {

    /**
     * Consrtuctor
     *
     * @param context activity context
     * @param name    database name
     * @param factory cursorfactory
     * @param version database version
     */
    DBHelper(Context context, @SuppressWarnings("SameParameterValue") String name, @SuppressWarnings("SameParameterValue") SQLiteDatabase.CursorFactory factory, @SuppressWarnings("SameParameterValue") int version) {
        super(context, name, factory, version);
    }

    /**
     * Instantiates a new Db helper.
     *
     * @param context the context
     */
    DBHelper(Context context) {
        super(context, DBConstants.DATABASE_NAME, null, 1);
    }

    private static DBHelper instance;

    /**
     * Gets helper.
     *
     * @param context the context
     * @return the helper
     */
    static synchronized DBHelper getHelper(Context context) {
        if(instance == null) {
            instance = new DBHelper(context);
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        expand(db, false);
    }


    @Override
    public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion) {

    }

    public static void reopen(Context context) {
        instance = new DBHelper(context);
    }
}

但是,可以通过 DBDAO.java 来检索,构造/实例化DBHelper本身:-

public class DBDAO {

    /**
     * The Db.
     */
    private SQLiteDatabase db;
    private DBHelper dbhelper;
    @SuppressWarnings("unused")
    private Context mContext;
    public static final String THISCLASS = DBDAO.class.getSimpleName();
    private static final String LOGTAG = "SW_DBDAO";

    /**
     * DBAO Constructor
     *
     * @param context Context of the invoking method
     */
    public DBDAO(Context context) {

        this.mContext = context;
        dbhelper = DBHelper.getHelper(context);
        db = dbhelper.getWritableDatabase();
    }

    public SQLiteDatabase getDb() {
        return db;
    }

    /**
     * Gets table row count.
     *
     * @param tablename table to inspect
     * @return number of rows
     */
    public int getTableRowCount(String tablename) {

        Cursor csr = db.query(tablename,null,null,null,null,null,null);
        int rv = csr.getCount();
        csr.close();     
        return rv;
    }

    /**
     * getTableRows - generic get rows from a table
     *
     * @param table      Table name
     * @param joinclause Joing clause, if blank skipped
     * @param filter     Filter clause less WHERE, if blank skipped
     * @param order      Order clause less ORDER BY keywords, skipped if blank
     * @return Cursor with extracted rows, if any.
     */
    public Cursor getTableRows(String table, @SuppressWarnings("SameParameterValue") String joinclause, String filter, String order) {

        String sql = " SELECT * FROM " + table;
        if (joinclause.length() > 0 ) {
            sql = sql + joinclause;
        }
        if (filter.length() > 0 ) {
            sql = sql + " WHERE " + filter;
        }
        if (order.length() > 0) {
            sql = sql + " ORDER BY " + order;
        }
        sql = sql + " ;";
        return db.query(table + joinclause,null,filter,null,null,null,order);
    }
}

其中一个表是过道,方法在

class DBAisleMethods {

    private Context context;
    private DBDAO dbdao;
    private static SQLiteDatabase db;
    private static long lastaisleadded;
    private static boolean lastaisleaddok = false;
    private static boolean lastaisleupdateok = false;
    private DBShopMethods dbshopmethods;
    public static final String THISCLASS = DBAisleMethods.class.getSimpleName();

    private final String[] dummyrowcolumns = new String[] {
            DBAislesTableConstants.AISLES_ID_COL,
            DBAislesTableConstants.AISLES_SHOPREF_COL,
            DBAislesTableConstants.AISLES_ORDER_COL,
            DBAislesTableConstants.AISLES_NAME_COL
    };
    private final MatrixCursor dummyrow = new MatrixCursor(dummyrowcolumns);

    /**
     * Instantiates a new Db aisle methods.
     *
     * @param ctxt the ctxt
     */
    DBAisleMethods(Context ctxt) {
        context = ctxt;
        dbdao = new DBDAO(context);
        db = dbdao.getDb();
        dbshopmethods = new DBShopMethods(context);
    }

    /**************************************************************************
     * getAisleCount - get the number of aisles
     *
     * @return number of Aisles
     */
    int getAisleCount() {
        return DBCommonMethods.getTableRowCount(db,
                DBAislesTableConstants.AISLES_TABLE
        );
    }


    /**************************************************************************
     * getLastAisleAdded - return the is of the last Aisle added
     *
     * @return id of the Aisle that was last added
     */
    @SuppressWarnings("unused")
    long getLastAisleAdded() {
        return lastaisleadded;
    }

    /**************************************************************************
     * ifAisleAdded - returns status of the last Aisle insert
     *
     * @return true if the last Aisle insert added the Aisle, else false
     */
    boolean ifAisleAdded() {
        return lastaisleaddok;
    }

    /**************************************************************************
     * insertAisle - add a new Aisle
     *
     * @param aislename name of the aisle
     * @param aislorder order of the aisle (within shop)
     * @param shopref   reference to the parent shop
     */
    void insertAisle(String aislename, int aislorder, long shopref) {

        long addedid;
        if (dbshopmethods.doesShopExist(shopref)) {
            ContentValues cv = new ContentValues();
            cv.put(DBAislesTableConstants.AISLES_NAME_COL, aislename);
            cv.put(DBAislesTableConstants.AISLES_ORDER_COL, aislorder);
            cv.put(DBAislesTableConstants.AISLES_SHOPREF_COL, shopref);
            addedid = db.insert(DBAislesTableConstants.AISLES_TABLE,
                    null,
                    cv);
            if (addedid > -1) {
                lastaisleadded = addedid;
                lastaisleaddok = true;

            }
        } else {
            lastaisleaddok = false;
        }
    }


    /**************************************************************************
     * @param aisleid    ID of the Aisle to modify
     * @param aisleorder new Aisle Order value (0 skips)
     * @param aislename  new Aisle Name value (blank skips)
     */
    void modifyAisle(long aisleid, int aisleorder, String aislename) {

        int updatecount = 0;
        ContentValues cv = new ContentValues();
        if (aisleorder > 0) {
            cv.put(DBAislesTableConstants.AISLES_ORDER_COL, aisleorder);
            updatecount++;
        }
        if (aislename.length() > 0) {
            cv.put(DBAislesTableConstants.AISLES_NAME_COL, aislename);
            updatecount++;
        }
        if (updatecount < 1) {
            return;
        }
        String[] whereargs = {Long.toString(aisleid)};
        String whereclause = DBAislesTableConstants.AISLES_ID_COL + " = ?";
        lastaisleupdateok = db.update(DBAislesTableConstants.AISLES_TABLE, cv, whereclause, whereargs) > 0;
    }

    /**************************************************************************
     * deleteAisle - Delete an Aisle and any children the aisle has
     * children could be :- productusage rows
     * shoplist rows
     * rule rows
     *
     * @param aisleid       id of the aisle to be deleted
     * @param intransaction true if already in a transaction
     */
    void deleteAisle(long aisleid, boolean intransaction) {

        @SuppressWarnings("unused") String sql;
        @SuppressWarnings("UnusedAssignment") int pudeletes = 0;
        @SuppressWarnings({"UnusedAssignment", "unused"}) int sldeletes = 0;
        @SuppressWarnings({"UnusedAssignment", "unused"}) int rdeletes = 0;
        @SuppressWarnings({"UnusedAssignment", "unused"}) int adelete = 0;

        if (doesAisleExist(aisleid)) {
            if (!intransaction) {
                db.beginTransaction();
            }

            //  Set whereargs string array to the aisleid as a string
            String[] whereargs = {Long.toString(aisleid)};
            // Delete ProductUsage rows that have Aisle as a parent
            pudeletes = db.delete(
                    DBProductusageTableConstants.PRODUCTUSAGE_TABLE,
                    DBProductusageTableConstants.PRODUCTUSAGE_AISLEREF_COL +
                            " = ?",
                    whereargs
            );

            // Delete Shopping List rows with Aisle as a parent
            //noinspection UnusedAssignment
            sldeletes = db.delete(
                    DBShopListTableConstants.SHOPLIST_TABLE,
                    DBShopListTableConstants.SHOPLIST_AISLEREF_COL +
                            " = ?",
                    whereargs
            );

            // Delete Rule rows with Aisle as a parent
            //noinspection UnusedAssignment
            rdeletes = db.delete(
                    DBRulesTableConstants.RULES_TABLE,
                    DBRulesTableConstants.RULES_AISLEREF_COL +
                            " = ?"
                    ,
                    whereargs);

            // Finally Delete the Aisle itself
            //noinspection UnusedAssignment
            adelete = db.delete(
                    DBAislesTableConstants.AISLES_TABLE,
                    DBAislesTableConstants.AISLES_ID_COL + " = ?",
                    whereargs);

            if (!intransaction) {
                db.setTransactionSuccessful();
                db.endTransaction();
            }
        }
    }

}

从以上内容可以看出,关系开始发挥作用;过道与儿童商店有关,过道可能是产品的父项,产品可能是ProductUsage的父项,而ProductUsage可能是ShoppingList的父项。

  • 这也是简化版本,为了简洁起见,删除了其他方法。

在活动中使用上述代码的示例可能是(以及其他代码):-

    dbshopmethods = new DBShopMethods(this);
    dbaislemethods = new DBAisleMethods(this);

    slcsr = dbshopmethods.getShops("", shopsorderby);
    selectshoplistadapter = new AdapterShopList(this,
            slcsr,
            CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER,
            getIntent(),
            true, false, false);

    selectshoplist.setAdapter(selectshoplistadapter);
    setSelectShopListener();

    alcsr = dbaislemethods.getAisles(shopfilter,orderby,false);
    aislelistadapter = new AdapterAisleList(
            this,
            alcsr,
            CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER,
            getIntent(),
            false, false, false
    );
    aiselist.setAdapter(aislelistadapter);
    aislesadapterset = true;

    aiselist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView,
                                View view,
                                int position,
                                long id) {
            listItemClick(view, position, id);
        }
    });
    aiselist.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> adapterView, View view,
                                       int position,
                                       long id) {
            listItemLongClick(view, position,id);
            return true;
        }
    });