1. 程式人生 > >android sqlite 的建立與使用,sqlite自定義框架。

android sqlite 的建立與使用,sqlite自定義框架。

android的四大儲存型別中,我們常用的sqlite資料庫。改資料庫為輕型資料庫,支援sql語句,據說是某一位大學教師所編寫的輕型資料庫。所上傳程式碼其實已經有一段歷史了。在我剛參加工作的時候,我的一位亦師亦友的同事,領我進入了資料的輕鬆時代。整個資料無外乎增刪改查,沒別的了,其實很簡單,但又很麻煩。。不說廢話了。直接上程式碼。

BaseService.java

public 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.java

在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>>

這些方法基本就可以滿足絕大部分的資料庫操作,個人認為及其的好用。說來慚愧,其實這個並不是我自己寫的,而是我那亦師亦友的小強童鞋寫的,一直用到現在,希望有耐性的人看完這個部落格,然後也能從中獲益,這個我認為是框架的東西給了我太多的啟發,也給我了很多的回憶。。我靠!!竟然抒情了!!!!