面向对象数据库编程
我们先看看操作示例
我们可以看到这里操作数据库只是引用了一个对象
IBaseDao<Person> baseDao = BaseDaoFactory.getInstance().getBaseDao(Person.class);
Person person = new Person();
person.name = "熊大";
person.setPassword(123456l);
baseDao.insert(person);
从上面的操作示例我们可以看到
1.自动建表
2.面向对象插入
我们先看一下BaseDaoFactory.getInstance().getBaseDao(Person.class);
从这里面的代码我们可以看到 这里调用SQLiteDatabase.openOrCreateDatabase(sqlPath, null);创建了一个库
getBaseDao(Class<T> entityClass)里面创建了一个BaseDao实例调用了init方法进行了初始化
public class BaseDaoFactory {
private static BaseDaoFactory ourInstance;
private final SQLiteDatabase mSqLiteDatabase;
public static BaseDaoFactory getInstance() {
if (ourInstance == null) {
ourInstance = new BaseDaoFactory();
}
return ourInstance;
}
private BaseDaoFactory() {
String sqlPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/app.db";
mSqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqlPath, null);
}
public synchronized <T>BaseDao getBaseDao(Class<T> entityClass) {
BaseDao<T> baseDao = null;
try {
baseDao = BaseDao.class.newInstance();
baseDao.init(entityClass,mSqLiteDatabase);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return baseDao;
}
}
紧接着我们看一下 baseDao.init(entityClass,mSqLiteDatabase);
这段代码我们可以看到 tableName = entityClass.getAnnotation(DBTable.class).value();
createTbale() 创建表的动作
这里获取了表明
public synchronized void init(Class<T> entity, SQLiteDatabase sqLiteDatabase) {
if (!isInit) {
entityClass = entity;
mSQLiteDatabase = sqLiteDatabase;
tableName = entityClass.getAnnotation(DBTable.class).value();
createTbale();
initCacheMap();
isInit = true;
}
}
上述代码我们看到 表名通过 获取实体类里的注解拿到的
那么我们看一下Person
我们可以看到@DBTable @DBFiled
@DBTable 表名 @DBFiled字段名
@DBTable("tb_person")
public class Person {
@DBFiled("tb_name")
public String name;
@DBFiled("tb_password")
public Long password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getPassword() {
return password;
}
public void setPassword(Long password) {
this.password = password;
}
}
@Target(ElementType.FIELD)//作用在成员变量上
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface DBFiled {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
String value();
}
上述代码我们看到了createTbale();创建表的一个操作我们看下是如何自动创建表的,我们看到是一个sql语句的拼接
private void createTbale() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("create table if not exists ");
stringBuilder.append(tableName);
stringBuilder.append("(");
//获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
Class type = field.getType();
if (type == String.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " TEXT,");
} else if (type == Double.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " DOUBLE,");
} else if (type == Integer.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " INTEGER,");
} else if (type == Float.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " FLOAT,");
} else if (type == byte[].class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " BLOB,");
} else if (type == Long.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " BIGINT,");
} else {
continue;
}
}
if (stringBuilder.charAt(stringBuilder.length() - 1) == ',') {
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
stringBuilder.append(")");
this.mSQLiteDatabase.execSQL(stringBuilder.toString());
}
剩下最后一步 通过对象插入数据 baseDao.insert(person); 遍历拿到字段名key, field.get(entity);拿到对应的属性
@Override
public void insert(T entity) {
ContentValues contentValues = getValuse(entity);
mSQLiteDatabase.insert(tableName, null, contentValues);
}
private ContentValues getValuse(T entity) {
ContentValues contentValues = new ContentValues();
Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Field> fieldEntry = iterator.next();
Field field = fieldEntry.getValue();
//表的字段名
String key = fieldEntry.getKey();
field.setAccessible(true);
try {
Object object = field.get(entity);
Class type = field.getType();
if (type == String.class) {
String vlaue = (String) object;
contentValues.put(key, vlaue);
} else if (type == Double.class) {
Double vlaue = (Double) object;
contentValues.put(key, vlaue);
} else if (type == Integer.class) {
Integer vlaue = (Integer) object;
contentValues.put(key, vlaue);
} else if (type == Float.class) {
Float vlaue = (Float) object;
contentValues.put(key, vlaue);
} else if (type == byte[].class) {
byte[] vlaue = (byte[]) object;
contentValues.put(key, vlaue);
} else if (type == Long.class) {
Long vlaue = (Long) object;
contentValues.put(key, vlaue);
} else {
continue;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return contentValues;
}
代码
Annotation
@Target(ElementType.FIELD)//作用在成员变量上
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface DBFiled {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
String value();
}
BaseDaoFactory
public class BaseDaoFactory {
private static BaseDaoFactory ourInstance;
private final SQLiteDatabase mSqLiteDatabase;
public static BaseDaoFactory getInstance() {
if (ourInstance == null) {
ourInstance = new BaseDaoFactory();
}
return ourInstance;
}
private BaseDaoFactory() {
String sqlPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/app.db";
mSqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqlPath, null);
}
public synchronized <T>BaseDao getBaseDao(Class<T> entityClass) {
BaseDao<T> baseDao = null;
try {
baseDao = BaseDao.class.newInstance();
baseDao.init(entityClass,mSqLiteDatabase);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return baseDao;
}
}
BaseDao
public interface IBaseDao<T> {
void insert(T entity);
List<T> query(T where);
void delte(T entity);
void update(T oldEntity ,T newEntity);
}
public class BaseDao<T> implements IBaseDao<T> {
/**
* 持有数据操作引用
*/
private SQLiteDatabase mSQLiteDatabase;
/**
* 操作的实体类
*/
private Class<T> entityClass;
/**
* 表名
*/
private String tableName;
/**
*缓存表的映射关系
*/
private HashMap<String, Field> cacheMap;
/**
* 是否初始化
*/
private boolean isInit = false;
public synchronized void init(Class<T> entity, SQLiteDatabase sqLiteDatabase) {
if (!isInit) {
entityClass = entity;
mSQLiteDatabase = sqLiteDatabase;
tableName = entityClass.getAnnotation(DBTable.class).value();
createTbale();
initCacheMap();
isInit = true;
}
}
/**
* 表的映射关系
*/
private void initCacheMap() {
cacheMap = new HashMap<>();
String sql = "select * from " + tableName + " limit 1,0";
Cursor cursor = mSQLiteDatabase.rawQuery(sql, null);
//获取表里面的字段名
String[] columnNames = cursor.getColumnNames();
// 获得该类的所有的公共(public)的字段,包括父类中的字段。
Field[] columnFields = entityClass.getFields();
for (String columnName : columnNames) {
Field reslutField = null;
for (Field field : columnFields) {
if (columnName.equals(field.getAnnotation(DBFiled.class).value())) {
reslutField = field;
break;
}
}
if (reslutField != null) {
cacheMap.put(columnName, reslutField);
}
}
cursor.close();
}
private static final String TAG = "BaseDao";
private void createTbale() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("create table if not exists ");
stringBuilder.append(tableName);
stringBuilder.append("(");
//获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
Class type = field.getType();
if (type == String.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " TEXT,");
} else if (type == Double.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " DOUBLE,");
} else if (type == Integer.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " INTEGER,");
} else if (type == Float.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " FLOAT,");
} else if (type == byte[].class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " BLOB,");
} else if (type == Long.class) {
stringBuilder.append(field.getAnnotation(DBFiled.class).value() + " BIGINT,");
} else {
continue;
}
}
if (stringBuilder.charAt(stringBuilder.length() - 1) == ',') {
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
stringBuilder.append(")");
this.mSQLiteDatabase.execSQL(stringBuilder.toString());
}
private ContentValues getValuse(T entity) {
ContentValues contentValues = new ContentValues();
Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Field> fieldEntry = iterator.next();
Field field = fieldEntry.getValue();
//表的字段名
String key = fieldEntry.getKey();
field.setAccessible(true);
try {
Object object = field.get(entity);
Class type = field.getType();
if (type == String.class) {
String vlaue = (String) object;
contentValues.put(key, vlaue);
} else if (type == Double.class) {
Double vlaue = (Double) object;
contentValues.put(key, vlaue);
} else if (type == Integer.class) {
Integer vlaue = (Integer) object;
contentValues.put(key, vlaue);
} else if (type == Float.class) {
Float vlaue = (Float) object;
contentValues.put(key, vlaue);
} else if (type == byte[].class) {
byte[] vlaue = (byte[]) object;
contentValues.put(key, vlaue);
} else if (type == Long.class) {
Long vlaue = (Long) object;
contentValues.put(key, vlaue);
} else {
continue;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return contentValues;
}
@Override
public void insert(T entity) {
ContentValues contentValues = getValuse(entity);
mSQLiteDatabase.insert(tableName, null, contentValues);
}
@Override
public List<T> query(T where) {
List<T> list = new ArrayList<>();
String condition = getCondition(where);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("select * from ");
stringBuffer.append(tableName);
stringBuffer.append(" where ");
stringBuffer.append(condition);
Cursor cursor = mSQLiteDatabase.rawQuery(stringBuffer.toString(), null);
while (cursor.moveToNext()) {
try {
T t = (T) where.getClass().newInstance();
Field[] fields = t.getClass().getFields();
String[] strings = cursor.getColumnNames();
for (Field field : fields) {
String key = field.getAnnotation(DBFiled.class).value();
for (String string : strings) {
if (key.equals(string)) {
Class<?> type = field.getType();
if (type == String.class) {
field.set(t, cursor.getString(cursor.getColumnIndex(string)));
} else if (type == Double.class) {
field.set(t, cursor.getDouble(cursor.getColumnIndex(string)));
} else if (type == Integer.class) {
field.set(t, cursor.getInt(cursor.getColumnIndex(string)));
} else if (type == Float.class) {
field.set(t, cursor.getFloat(cursor.getColumnIndex(string)));
} else if (type == byte[].class) {
field.set(t, cursor.getBlob(cursor.getColumnIndex(string)));
} else if (type == Long.class) {
field.set(t, cursor.getLong(cursor.getColumnIndex(string)));
} else {
continue;
}
}
}
}
list.add(t);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
cursor.close();
return list;
}
@Override
public void delte(T entity) {
String condition = getCondition(entity);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("delete from ");
stringBuffer.append(tableName);
stringBuffer.append(" where ");
stringBuffer.append(condition);
mSQLiteDatabase.execSQL(stringBuffer.toString());
}
/**
* @param oldEntity 更新条件
* @param newEntity 更新的字段
* @return
*/
@Override
public void update(T oldEntity, T newEntity) {
String old = getCondition(oldEntity);
String n = getCondition(newEntity, " , ");
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("update ");
stringBuffer.append(tableName);
stringBuffer.append(" set ");
stringBuffer.append(n);
stringBuffer.append(" where ");
stringBuffer.append(old);
Log.i(TAG, "update: " + stringBuffer.toString());
mSQLiteDatabase.execSQL(stringBuffer.toString());
}
private String getCondition(T entity) {
return getCondition(entity, " and ");
}
private String getCondition(T entity, String tag) {
Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
StringBuffer stringBuffer = new StringBuffer();
while (iterator.hasNext()) {
Map.Entry<String, Field> fieldEntry = iterator.next();
Field field = fieldEntry.getValue();
//表的字段名
String key = fieldEntry.getKey();
try {
Object object = field.get(entity);
if (object != null) {
if (stringBuffer.length() > 0) {
stringBuffer.append(tag);
}
stringBuffer.append(key);
stringBuffer.append(" = ");
stringBuffer.append("'");
stringBuffer.append(object.toString());
stringBuffer.append("'");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return stringBuffer.toString();
}
}
Person 可以任意创建这里只是个演示bean
@DBTable("tb_person")
public class Person {
@DBFiled("tb_name")
public String name;
@DBFiled("tb_password")
public Long password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getPassword() {
return password;
}
public void setPassword(Long password) {
this.password = password;
}
}
实际操作
final IBaseDao<Person> baseDao = BaseDaoFactory.getInstance().getBaseDao(Person.class);
findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Person person = new Person();
person.name = name;
person.setPassword(password++);
baseDao.insert(person);
}
});
findViewById(R.id.remove).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Person person = new Person();
person.name = name;
person.password = password++;
baseDao.delte(person);
}
});
findViewById(R.id.query).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Person person = new Person();
person.name = name;
List<Person> list = baseDao.query(person);
for (Person person1 : list) {
Log.i(TAG, "name= " + person1.name + " passowrd=" + person1.password);
}
}
});
findViewById(R.id.update).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Person old = new Person();
old.name = name;
old.password = 26l;
Person n = new Person();
n.name = "无敌";
baseDao.update(old, n);
}
});