简介
- BaseDaoFactory 数据库创建,初始化
- IBaseDao 增删改查接口
- BaseDao 增删改查具体的实现
- User 增删改查的对象
- DbField 数据库字段名字标注
- DbTable 数据库表名注解
我们这里只要是学习对象型数据库实现原理,如果要直接使用,可以查看GreenDao直接使用
BaseDaoFactory
public class BaseDaoFactory {
private static final BaseDaoFactory instance = new BaseDaoFactory();
//定义建数据库的路劲
private String sqliteDatabasePath;
private SQLiteDatabase sqLiteDatabase;
public static BaseDaoFactory getInstance() {
return instance;
}
public BaseDaoFactory() {
//新建数据库
//数据库路径,建议创建在sdcard上面,即使卸载了,数据库依然存在
// sqliteDatabasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "zkq.db";
sqliteDatabasePath = "data/data/com.example.db_project/zkq.db";
sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqliteDatabasePath, null);
}
public <T> BaseDao<T> getBaseDao(Class<T> entityClass) {
BaseDao baseDao = null;
try {
baseDao = BaseDao.class.newInstance();
baseDao.init(sqLiteDatabase, entityClass);
} catch (Exception e) {
e.printStackTrace();
}
return baseDao;
}
}
BaseDao中
initCacheMap方法,将数据库中的字段和传入的user字段匹配,如果数据库中的字段名字和user的变量名字相匹配,就存入cacheMap中,方便读取
getValues方法,将user中的字段读取出来,放回一个Map<String,String>
下面是BaseDao全部代码
public class BaseDao<T> implements IBaseDao<T> {
private static final String TAG = "BaseDao";
//持有数据库操作的引用
private SQLiteDatabase sqLiteDatabase;
//持有操作数据库所对应的java类型
private Class<T> entityClass;
//表名
private String tableName;
//定义一个缓存空间(key-字段名 value-成员变量)
private HashMap<String, Field> cacheMap;
//标记:用来表示是否做过初始化操作
private boolean isInit = false;
public void init(SQLiteDatabase sqLiteDatabase, Class<T> entityClass) {
this.sqLiteDatabase = sqLiteDatabase;
this.entityClass = entityClass;
//可以根据传入的entityClass类型来建表,只需要建一次
if(!isInit){
//自动建表
//取得表明
if(entityClass.getAnnotation(DbTable.class) == null){
//反射到类名
this.tableName = entityClass.getSimpleName();
} else {
//取得注解上的名字
this.tableName = entityClass.getAnnotation(DbTable.class).value();
}
//执行建表操作
// create table if not exists tb_user(_id TEXT,name TEXT,password TEXT)
//使用getCreateTableSql() 生成sql语句
String createTableSql = getCreateTableSql();
Log.i(TAG, createTableSql);
this.sqLiteDatabase.execSQL(createTableSql);
cacheMap = new HashMap<>();
initCacheMap();
isInit = true;
}
}
/**
* 初始化数据表字段
* 将数据库中的字段和传入的user字段匹配,如果数据库中的字段名字和user的变量名字相匹配,就存入cacheMap中,方便读取
*/
private void initCacheMap() {
//1、取得所有字段名
String sql = "select * from " + tableName + " limit 1, 0"; //空表
Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
String[] columnNames = cursor.getColumnNames();
//2、取所有的成员变量
Field[] declaredFields = entityClass.getDeclaredFields();
//把所有字段的访问权限打开
for (Field f: declaredFields) {
f.setAccessible(true);
}
//字段 跟 成员变量一一对应
for(String columNage : columnNames){
Field columnField = null;
for(Field field : declaredFields){
String fieldName = ""; //对象中的成员变量名字
if(field.getAnnotation(DbField.class) != null){
fieldName = field.getAnnotation(DbField.class).value();
} else {
fieldName = field.getName();
}
if(columNage.equals(fieldName)){ //匹配
columnField = field;
break;
}
}
if(columnField != null){
cacheMap.put(columNage, columnField);
}
}
}
/**
* 建表的sql语句
*
* @return
*/
private String getCreateTableSql() {
//create table if not exists tb_user(_id TEXT,name TEXT,password TEXT,status INTEGER)
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("create table if not exists ");
stringBuffer.append(tableName + "(");
//反射得到所有的成员变量
Field[] declaredFields = entityClass.getDeclaredFields();
for (Field field : declaredFields) {
Class type = field.getType();// 拿到成员的类型
if(field.getAnnotation(DbField.class) != null){
//通过注解获取
if(type == String.class){
stringBuffer.append(field.getAnnotation(DbField.class).value() + " TEXT,");
} else if(type == Integer.class){
stringBuffer.append(field.getAnnotation(DbField.class).value() + " INTEGER,");
}else if(type == Long.class){
stringBuffer.append(field.getAnnotation(DbField.class).value() + " BIGINT,");
}else if(type == Double.class){
stringBuffer.append(field.getAnnotation(DbField.class).value() + " DOUBLE,");
}else if(type == byte[].class){
stringBuffer.append(field.getAnnotation(DbField.class).value() + " BLOB,");
}else {
//不支持的类型
continue;
}
} else {
//通过反射获取
if(type == String.class){
stringBuffer.append(field.getName() + " TEXT,");
} else if(type == Integer.class){
stringBuffer.append(field.getName() + " INTEGER,");
}else if(type == Long.class){
stringBuffer.append(field.getName() + " BIGINT,");
}else if(type == Double.class){
stringBuffer.append(field.getName() + " DOUBLE,");
}else if(type == byte[].class){
stringBuffer.append(field.getName() + " BLOB,");
}else {
//不支持的类型
continue;
}
}
}
if(stringBuffer.charAt(stringBuffer.length() - 1) == ','){
stringBuffer.deleteCharAt(stringBuffer.length() - 1);
}
stringBuffer.append(")");
return stringBuffer.toString();
}
@Override
public long insert(T entity) {
//1、准本好ContentValues中需要的数据
Map<String, String> map = getValues(entity);
//2、把数据转移到ContentValues
ContentValues values = getContentValues(map);
//3、开始插入
long result = sqLiteDatabase.insert(tableName, null, values);
return result;
}
/**
*
* @param map 成员变量的名字 成员变量的值
* @return
*/
private ContentValues getContentValues(Map<String, String> map) {
ContentValues contentValues = new ContentValues();
Set keys = map.keySet();
Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()){
String key = iterator.next();
String value = map.get(key);
if(value != null){
contentValues.put(key, value);
}
}
return contentValues;
}
/**
* 将entity的字段放入到map中
* @param entity
* @return
*/
private Map<String, String> getValues(T entity) {
HashMap<String, String> map = new HashMap<>();
//返回的是所有的成员变量
Iterator<Field> iterator = cacheMap.values().iterator();
while (iterator.hasNext()){
Field field = iterator.next();
field.setAccessible(true);
try {
//获取对象的属性的值
Object obj = field.get(entity);
if(obj == null){
continue;
}
String value = obj.toString();
String key = "";
if(field.getAnnotation(DbField.class) != null){
key = field.getAnnotation(DbField.class).value();
} else {
key = field.getName();
}
if(!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)){
map.put(key, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return map;
}
@Override
public int update(T entity, T where) {
int result = -1;
//1、准本好ContentValues中需要的数据
Map<String, String> values = getValues(entity);
ContentValues contentValues = getContentValues(values);
//条件map
Map<String, String> values1 = getValues(where);
Condition condition = new Condition(values1);
result = sqLiteDatabase.update(tableName, contentValues, condition.whereClause, condition.whereArgs);
return result;
}
@Override
public int delete(T where) {
int result = -1;
//1、准本好ContentValues中需要的数据
Map<String, String> values = getValues(where);
Condition condition = new Condition(values);
result = sqLiteDatabase.delete(tableName, condition.whereClause, condition.whereArgs);
return result;
}
@Override
public List<T> query(T where) {
return query(where, null, null, null);
}
@Override
public List<T> query(T where, String orderBy, Integer startIndex, Integer limit) {
// sqLiteDatabase.query(tableName, null, "id = ?",
// new String[], null. null, orderBy, "1, 5");
//1、准本好ContentValues中需要的数据
Map<String, String> values = getValues(where);
String limitString = ""; //"2,6"
if(startIndex != null && limit != null){
limitString = startIndex + " , " + limit;
}
Condition condition = new Condition(values);
Cursor query = sqLiteDatabase.query(tableName, null, condition.whereClause,
condition.whereArgs, null, orderBy, limitString);
List<T> result = getResult(query, where); //游标 --- 》 javabean --- list<javabaen>
return result;
}
private List<T> getResult(Cursor query, T where) {
ArrayList list = new ArrayList();
Object item = null;
while (query.moveToNext()){
try {
item = where.getClass().newInstance(); //因为不知道 new ? , 所以通过反射方式
//cacheMap (字段---成员变量的名字)
Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<String, Field> entry = iterator.next();
//取列名
String columnName = entry.getKey();
//以列名拿到列名在游标中的位置
int columnIndex = query.getColumnIndex(columnName);
Field value = entry.getValue(); //id
Class<?> type = value.getType(); //Integer
if(columnIndex != -1){ //columnName = "age"
if(type==String.class){
value.set(item,query.getString(columnIndex));//setid(1)
}else if(type==Double.class){
value.set(item,query.getDouble(columnIndex));
}else if(type==Integer.class){
value.set(item,query.getInt(columnIndex));
}else if(type==Long.class){
value.set(item,query.getLong(columnIndex));
}else if(type==byte[].class){
value.set(item,query.getBlob(columnIndex));
}else{
continue;
}
}
}
list.add(item);
} catch (Exception e) {
e.printStackTrace();
}
}
query.close();
return list;
}
private class Condition {
private String whereClause; //1=1 and password = ? --- >password = ?
private String[] whereArgs;
/**
* new Person(1, "alan", "123")
* @param whereCasue
*/
public Condition(Map<String, String> whereCasue ) {
ArrayList list = new ArrayList(); //whereArgs里面的内容存入的list
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("1=1");
//取得所有成员变量的名字
Set<String> keys = whereCasue.keySet();
Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()){
String key = iterator.next();
String value = whereCasue.get(key);
if(value != null){
stringBuffer.append(" and " + key + "=?");
list.add(value);
}
}
this.whereClause = stringBuffer.toString();
this.whereArgs = (String[]) list.toArray(new String[list.size()]);
}
}
}
User代码
/**
* 如果没有设置DbTable 数据库表名就是tb_user
* 设置了DbTable,数据库表名就是User
*/
@DbTable("tb_user")
public class User {
/**
* 如果没有设置DbField 数据库保存的就是id
* 设置了DbField,数据库字段就是_id
*/
@DbField("_id")
private String id;
private String name;
private String password;
public User() {
}
public User(String id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
DbTable代码
/**
* 表名
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DbTable {
String value();
}
DbField代码
/**
* 字段名
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DbField {
String value();
}
在mainActivity中具体使用
/**
* 插入
* @param view
*/
public void insert(View view) {
BaseDao baseDao = BaseDaoFactory.getInstance().getBaseDao(User.class);
baseDao.insert(new User("1", "zhangsan", "111111"));
baseDao.insert(new User("2", "lisi", "222222"));
baseDao.insert(new User("3", "wangwu", "333333"));
baseDao.insert(new User("4", "zhaoliu", "444444"));
baseDao.insert(new User("5", "liqi", "555555"));
}
/**
* 修改
* @param view
*/
public void clickUpdate(View view) {
BaseDao baseDao = BaseDaoFactory.getInstance().getBaseDao(User.class);
User user = new User("5","liqi","666666");
User where = new User("5","","");
baseDao.update(user,where);
}
/**
* 删除
* @param view
*/
public void clickDelete(View view) {
BaseDao baseDao = BaseDaoFactory.getInstance().getBaseDao(User.class);
User where = new User("2","","");
baseDao.delete(where);
}
/**
* 查询
* @param view
*/
public void clickSelect(View view) {
BaseDao baseDao = BaseDaoFactory.getInstance().getBaseDao(User.class);
User user = new User();
List<User> users = baseDao.query(user);
for (User user1 : users) {
Log.e(TAG,user1.toString());
}
}