android sqlite 的建立與使用,sqlite自定義框架。
android的四大儲存型別中,我們常用的sqlite資料庫。改資料庫為輕型資料庫,支援sql語句,據說是某一位大學教師所編寫的輕型資料庫。所上傳程式碼其實已經有一段歷史了。在我剛參加工作的時候,我的一位亦師亦友的同事,領我進入了資料的輕鬆時代。整個資料無外乎增刪改查,沒別的了,其實很簡單,但又很麻煩。。不說廢話了。直接上程式碼。
BaseService.java
DataBaseFactory.javapublic class BaseService { /** 插入一個表(實體類)的資料 */ public static <T> Integer insert(T entity) { Class<?> clazz = entity.getClass(); String tableName = clazz.getAnnotation(Table.class).name(); Field[] fieldArray = clazz.getDeclaredFields(); ContentValues content = new ContentValues(); String fieldName; Field field; Object value; for(int i=0;i<fieldArray.length;i++) { field = fieldArray[i]; fieldName = field.getName(); value = ReflectUtil.getValue(entity, fieldName); if(value instanceof String) { content.put(fieldName, (String)value); } else if(value instanceof Integer) { content.put(fieldName, (Integer)value); } else if(value instanceof Long) { content.put(fieldName, (Long)value); } else if(value instanceof Double) { content.put(fieldName, (Double)value); }else if(value == null) { content.putNull(fieldName); } } DataBaseFactory.getDb().insert(tableName, null, content); return 1; } /** 插入多個表(實體類)的資料 */ public static <T> Integer insert(List<T> entitys) { if(entitys != null && entitys.size() != 0) { Class<?> clazz = entitys.get(0).getClass(); String tableName = clazz.getAnnotation(Table.class).name(); ContentValues content = null; Field[] fieldArray = clazz.getDeclaredFields(); SQLiteDatabase dataBase = DataBaseFactory.getDb(); dataBase.beginTransaction(); for(T entity : entitys) { content = new ContentValues(); String fieldName; Field field; Object value; for(int i=0;i<fieldArray.length;i++) { field = fieldArray[i]; fieldName = field.getName(); value = ReflectUtil.getValue(entity, fieldName); if(value instanceof String) { content.put(fieldName, (String)value); } else if(value instanceof Integer) { content.put(fieldName, (Integer)value); } else if(value instanceof Long) { content.put(fieldName, (Long)value); } else if(value instanceof Double) { content.put(fieldName, (Double)value); }else if(value == null) { content.putNull(fieldName); } } dataBase.insert(tableName, null, content); } dataBase.setTransactionSuccessful(); dataBase.endTransaction(); return 1; } return null; } /** 更新一個表(實體類)的資料 */ public static <T> Integer update(T entity) { Class<?> clazz = entity.getClass(); String tableName = clazz.getAnnotation(Table.class).name(); String id = clazz.getAnnotation(Id.class).name(); Field[] fieldArray = clazz.getDeclaredFields(); Object primaryKeyValue = ReflectUtil.getValue(entity, id); if(primaryKeyValue == null) { return 0; } ContentValues content = new ContentValues(); String fieldName; Field field; Object value; for(int i=0;i<fieldArray.length;i++) { field = fieldArray[i]; fieldName = field.getName(); value = ReflectUtil.getValue(entity, fieldName); if(!fieldName.equals(id)) { if(value instanceof String) { content.put(fieldName, (String)value); } else if(value instanceof Integer) { content.put(fieldName, (Integer)value); } else if(value instanceof Long) { content.put(fieldName, (Long)value); } else if(value instanceof Double) { content.put(fieldName, (Double)value); } else if(value == null) { content.putNull(fieldName); } } } Integer result = DataBaseFactory.getDb().update(tableName, content, id+"=?", new String[] {primaryKeyValue.toString()}); return result; } /** 查詢一個表(實體類)的資料 第一個為Id,第二個為表(實體類) */ @SuppressWarnings("unchecked") public static <T> T findOne(Serializable id, Class<?> clazz) { String tableName = clazz.getAnnotation(Table.class).name(); String idName = clazz.getAnnotation(Id.class).name(); Field[] fieldArray = clazz.getDeclaredFields(); String sql = "select * from " + tableName + " where " + idName + " = '" + id + "'"; Cursor cursor = DataBaseFactory.getDb().rawQuery(sql, null); T entity = null; String fieldName; Field field; Class<?> type; int index; if(cursor.moveToNext()) { try { entity = (T) clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } for(int i=0;i<fieldArray.length;i++) { field = fieldArray[i]; fieldName = field.getName(); type = field.getType(); index = cursor.getColumnIndex(fieldName); Object value = null; if(type.equals(String.class)) { value = cursor.getString(index); } else if(type.equals(Integer.class)) { value = cursor.getInt(index); } else if(type.equals(Long.class)) { value = cursor.getLong(index); } else if(type.equals(Double.class)) { value = cursor.getDouble(index); } ReflectUtil.setValue(entity, fieldName, value); } } cursor.close(); return entity; } /** 查詢一個表(實體類)的所有資料 */ @SuppressWarnings("unchecked") public static <T> List<T> findAll(Class<?> clazz) { String tableName = clazz.getAnnotation(Table.class).name(); Field[] fieldArray = clazz.getDeclaredFields(); String sql = "select * from " + tableName; Cursor cursor = DataBaseFactory.getDb().rawQuery(sql, null); String fieldName; Field field; Class<?> type; int index; T entity = null; List<T> list = new ArrayList<T>(); while(cursor.moveToNext()) { try { entity = (T) clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } for(int i=0;i<fieldArray.length;i++) { field = fieldArray[i]; fieldName = field.getName(); type = field.getType(); index = cursor.getColumnIndex(fieldName); Object value = null; if(type.equals(String.class)) { value = cursor.getString(index); } else if(type.equals(Integer.class)) { value = cursor.getInt(index); } else if(type.equals(Long.class)) { value = cursor.getLong(index); } else if(type.equals(Double.class)) { value = cursor.getDouble(index); } ReflectUtil.setValue(entity, fieldName, value); } list.add(entity); } cursor.close(); return list.size() != 0 ? list : null; } /** 刪除一個表(實體類)的某一個數據資料 第一個為Id,第二個為表明(實體類) */ public static Integer deleteOne(Serializable id, Class<?> clazz) { String tableName = clazz.getAnnotation(Table.class).name(); String idName = clazz.getAnnotation(Id.class).name(); Integer result = DataBaseFactory.getDb().delete(tableName, idName+"=?", new String[] {id.toString()}); return result; } /** 刪除一個表(實體類)的多個數據資料 第一個為Id的集合,第二個為表名(實體類) */ public static void deleteMore(List<Serializable> ids, Class<?> clazz) { if(ids != null && ids.size() != 0) { for(Serializable id : ids) { deleteOne(id, clazz); } } } /** 刪除一個表(實體類)的資料 */ public static void deleteAll(Class<?> clazz) { String tableName = clazz.getAnnotation(Table.class).name(); DataBaseFactory.getDb().delete(tableName, null, null); } /** 查詢一個表(實體類)的資料 第一個為sql語句,第二個為sql中佔位符的值,第三個為表名(實體類) */ @SuppressWarnings("unchecked") public static <T> List<T> queryForEntitys(String sql, String[] paramValues, Class<?> clazz) { Field[] fieldArray = clazz.getDeclaredFields(); Cursor cursor = DataBaseFactory.getDb().rawQuery(sql, paramValues); String fieldName; Field field; Class<?> type; int index; T entity = null; List<T> list = new ArrayList<T>(); while(cursor.moveToNext()) { try { entity = (T) clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } for(int i=0;i<fieldArray.length;i++) { field = fieldArray[i]; fieldName = field.getName(); type = field.getType(); index = cursor.getColumnIndex(fieldName); if(index != -1) { Object value = null; if(type.equals(String.class)) { value = cursor.getString(index); } else if(type.equals(Integer.class)) { value = cursor.getInt(index); } else if(type.equals(Long.class)) { value = cursor.getLong(index); } else if(type.equals(Double.class)) { value = cursor.getDouble(index); } ReflectUtil.setValue(entity, fieldName, value); } } list.add(entity); } cursor.close(); return list.size() != 0 ? list : null; } /** 查詢一個表(實體類)的一條資料資料 第一個為sql語句,第二個為sql中佔位符的值,第三個為表名(實體類) */ @SuppressWarnings("unchecked") public static <T> T queryForEntity(String sql, String[] paramValues, Class<?> clazz) { Field[] fieldArray = clazz.getDeclaredFields(); Cursor cursor = DataBaseFactory.getDb().rawQuery(sql, paramValues); if(cursor.getCount() > 1) { throw new RuntimeException("記錄超過一條!"); } T entity = null; String fieldName; Field field; Class<?> type; int index; if(cursor.moveToNext()) { try { entity = (T) clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } for(int i=0;i<fieldArray.length;i++) { field = fieldArray[i]; fieldName = field.getName(); type = field.getType(); index = cursor.getColumnIndex(fieldName); if(index != -1) { Object value = null; if(type.equals(String.class)) { value = cursor.getString(index); } else if(type.equals(Integer.class)) { value = cursor.getInt(index); } else if(type.equals(Long.class)) { value = cursor.getLong(index); } else if(type.equals(Double.class)) { value = cursor.getDouble(index); } ReflectUtil.setValue(entity, fieldName, value); } } } cursor.close(); return entity; } /** 查詢一個表(實體類)的資料 第一個為sql語句,第二個為sql中佔位符的值 返回list<map> 適合複雜查詢 */ public static List<Map<String, Object>> queryForMaps(String sql, String[] paramValues) { Cursor cursor = DataBaseFactory.getDb().rawQuery(sql, paramValues); List<Map<String, Object>> list = new ArrayList<Map<String,Object>>(); Map<String, Object> map; int index; while(cursor.moveToNext()) { map = new HashMap<String, Object>(); String[] names = cursor.getColumnNames(); for(String name : names) { index = cursor.getColumnIndex(name); map.put(name, cursor.getString(index)); } list.add(map); } cursor.close(); return list.size() != 0 ? list : null; } /** 查詢一個表(實體類)的資料 第一個為sql語句,第二個為sql中佔位符的值 返回list<map> 適合複雜查詢 */ public static Map<String, Object> queryForMap(String sql, String[] paramValues) { Cursor cursor = DataBaseFactory.getDb().rawQuery(sql, paramValues); if(cursor.getCount() > 1) { throw new RuntimeException("記錄超過一條!"); } Map<String, Object> map = null; int index; if(cursor.moveToNext()) { map = new HashMap<String, Object>(); String[] names = cursor.getColumnNames(); for(String name : names) { index = cursor.getColumnIndex(name); map.put(name, cursor.getString(index)); } } cursor.close(); return map; } }
在DataBaseFactory中,可以通過DBNAME來命名我們的資料檔名稱,通過entityClasses陣列來新增我們的JavaBean來建立表。例如:Test1.class、Test2.class。
public class DataBaseFactory extends SQLiteOpenHelper { private static final String DBNAME = "sale-xiao-manage.db";//資料庫檔名稱 private static final int DBVERSION = 1; private static SQLiteDatabase db; private Class<?>[] entityClasses = {Test1.class,Test2.class};//新增庫表 /** * 構造方法,直接初始化一個SQLiteDatabase物件用來操作所有的資料相關方法 */ public DataBaseFactory(Context context) { super(context, DBNAME, null, DBVERSION); db = getWritableDatabase();// getWritableDatabase()可以用於讀寫,如果getReadableDatabase()就只能進讀的操作。 } @Override public void onCreate(SQLiteDatabase db) { String fieldName; Class<?> type; String tableName; String id; for(Class<?> clazz : entityClasses) { String execSql = "CREATE TABLE IF NOT EXISTS "; tableName = clazz.getAnnotation(Table.class).name(); id = clazz.getAnnotation(Id.class).name(); execSql += tableName + " (" + id + " TEXT not null,"; Field[] fieldArray = clazz.getDeclaredFields(); for(Field field : fieldArray) { fieldName = field.getName(); if(!fieldName.equals(id)) { type = field.getType(); if(type.equals(String.class)) { execSql += fieldName + " TEXT,"; } else if(type.equals(Integer.class) || type.equals(Long.class)) { execSql += fieldName + " INTEGER,"; } else if(type.equals(Double.class)) { execSql += fieldName + " DOUBLE,"; } } } execSql = execSql.substring(0, execSql.length()-1) + ")"; db.execSQL(execSql); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { String tableName; List<Object> list = new ArrayList<Object>(); for(Class<?> clazz : entityClasses) { tableName = clazz.getAnnotation(Table.class).name(); list = BaseService.findAll(clazz); db.execSQL("DROP TABLE IF EXISTS " + tableName); onCreate(db); BaseService.insert(list); } } public static SQLiteDatabase getDb() { return db; } public static void closeDB() { db.close(); } }
ReflectUtil.java
public class ReflectUtil { /** * 獲取實體類一個成員變數的值 */ public static Object getValue(Object entity, String fieldName) { Object value = null; try { Class<?> clazz = entity.getClass(); String methodName = "get" + StrUtil.getUpperCharAt(fieldName, 0); Method method = clazz.getMethod(methodName); value = method.invoke(entity); } catch (Exception e) { e.printStackTrace(); } return value; } public static void setValue(Object entity, String fieldName, Object value) { try { Class<?> clazz = entity.getClass(); Class<?> type = clazz.getDeclaredField(fieldName).getType(); String methodName = "set" + StrUtil.getUpperCharAt(fieldName, 0); Method method = clazz.getMethod(methodName, type); if(value != null) { if(type.equals(Integer.class)) { value = Integer.parseInt(value.toString()); } else if(type.equals(Double.class)) { value = Double.parseDouble(value.toString()); } else if(type.equals(Long.class)) { value = Long.parseLong(value.toString()); } } method.invoke(entity, new Object[] {value}); } catch (Exception e) { e.printStackTrace(); } } }
StrUtil.java
public class StrUtil {
/**
* 把字串的指定字母大寫
*/
public static String getUpperCharAt(String str, int index) {
String result = null;
int count = str.length();
if(count > index) {
String start = str.substring(0, index);
String at = (str.charAt(index) + "").toUpperCase();
String end = str.substring(index+1);
result = start + at + end;
}
return result;
}
/**
* 把字串中的特殊字元轉義符轉換回特殊字元
*/
public static String specialFormat(String str) {
str = str.replace("\"", "<syh>");
str = str.replace("\r\n", "<hhf>");
str = str.replace("\\", "<xg>");
return str;
}
public static String specialUnFormat(String str) {
str = str.replace("<syh>", "\"");
str = str.replace("<hhf>", "\r\n");
str = str.replace("<xg>", "\\");
return str;
}
}
Table.java
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
public String name();
}
Id.java
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
public String name();
}
以上就是建立資料庫所用到的核心內容了。其中Table,Id都是工具類,為了直接通過JavaBean來建立表所服務的。如果我們想建立一個表,並且定義一個表結構,只需要建立一個JavaBean就可以了。例如Test1.java
Test1.java
@Table(name = "t_a_test1") //此處為表名稱
@Id(name = "testId") //此處為表主鍵名稱
public class Test1 {
private Integer testId;
private String content;
private String remark;
private Long number;
public Integer getTestId() {
return testId;
}
public void setTestId(Integer testId) {
this.testId = testId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Long getNumber() {
return number;
}
public void setNumber(Long number) {
this.number = number;
}
}
下面來介紹下怎麼使用這個我認為已經趨近於框架的東西。
首先,我們需要初始化他,個人建議在MyApplication中初始化就可以了。
new DataBaseFactory(this);//初始化資料庫
這個時候,在我們DataBaseFactory.java 中的 entityClasses陣列中就已經初始化(沒有則建立)各種表了。
然後就是使用了。我們來分別說一下增刪改查吧。
新增(修改):
private void insert(){
List<Test1> list = new ArrayList<Test1>();
for (Integer i = 0; i < 10; i++) {
Long number = Long.valueOf("15000000000");
Test1 test = new Test1();
test.setTestId(i);//可以不新增主鍵,會自增長
test.setContent("我是Content" + i);
test.setRemark("我是Remark" + i);
test.setNumber(number ++);
list.add(test);
// BaseService.insert(test);//插入單條(根據主鍵可進行“改”的操作。)
}
BaseService.insert(list);//多條插入(根據主鍵可進行“改”的操作。)
}
這樣就可以進行新增或修改了,如果某一條的主鍵存在,則根據所傳入的某一條test進行修改。已經封裝好了可以進行單條、多條的新增與修改。在新增的時候主鍵可以不進行設定,如果不進行setTestId()則主鍵會自增長。
刪除:
private void delete(){
//刪除單條資料
int id = 111;
BaseService.deleteOne(id, Test1.class);
//刪除多條資料
List<Serializable> list = new ArrayList<Serializable>();
for(Integer i = 20; i > 0; i ++){
list.add(i);
}
BaseService.deleteMore(list, Test1.class);
//清空表Test1
BaseService.deleteAll(Test1.class);
}
這裡提供了單條刪除,多條刪除和清空表資料。
查詢:
private void selector(){
Test1 test = new Test1();
List<Test1> list = new ArrayList<Test1>();
Map<String, Object> map = new HashMap<String, Object>();
List<Map<String, Object>> listMap = new ArrayList<Map<String,Object>>();
//單條查詢
int id = 1;
test = BaseService.findOne(id, Test1.class);//無條件單條查詢
//全部查詢
list = BaseService.findAll(Test1.class);//無條件全部查詢
//通過sql語句進行有條件查詢
//第一個引數為sql語句 其中所需要的查詢條件通過佔位符?來進行佔位, 第二個引數為String[] 按照順序來填充第一引數中的佔位符 如果無佔位符可傳null, 第三個引數為資料表對應JavaBean
test = BaseService.queryForEntity("select * from t_a_test1 where number = ?", new String[]{"15000000000"}, Test1.class);//返回值為單個Test1
list = BaseService.queryForEntitys("select * from t_a_test1 where number = ?", new String[]{"15000000000"}, Test1.class);//返回值為list,含多個Test1
map = BaseService.queryForMap("select * from t_a_test1 where number = ?", new String[]{"15000000000"});//返回值為Tset1轉換成的Map
listMap = BaseService.queryForMaps("select * from t_a_test1 where number = ?", new String[]{"15000000000"});//返回值為多個Test1轉換成的List<Map>
}
查詢方式有六種,分別為:
1.通過單個id無限制條件查詢,返回單個JavaBean
2.通過多個id無限制條件查詢、返回List<JavaBean>
3.通過sql語句與佔位符進行有條件單個查詢,返回單個JavaBean
4.通過sql語句與佔位符進行有條件多個查詢,返回List<JavaBean>
5.通過sql語句與佔位符進行有條件單個查詢,返回單個Map<String, Object>
6.通過sql語句與佔位符進行有條件多個查詢,返回List<Map<String, Object>>
這些方法基本就可以滿足絕大部分的資料庫操作,個人認為及其的好用。說來慚愧,其實這個並不是我自己寫的,而是我那亦師亦友的小強童鞋寫的,一直用到現在,希望有耐性的人看完這個部落格,然後也能從中獲益,這個我認為是框架的東西給了我太多的啟發,也給我了很多的回憶。。我靠!!竟然抒情了!!!!