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