使用注解和反射构建通用数据库框架

转载请注明出处:

下面我们写一个操作数据库框架的示例,从而熟悉注解,反射,泛型的使用。

通过实体类创建和删除操作,因为操作数据库中的表不同,那么对应的实体类也不同,我们需要使用泛型来指定操作的实体类。使用注解使实体类和数据库表列一一对应。

DbHelper.java

public class DbHelper extends SQLiteOpenHelper {private static String NAME = "db.db";private static int VERSION = 1;public DbHelper(Context context) {super(context, NAME, null, VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}}

Dao.java

public interface Dao<T> {/** * 插入数据 * * @param t */public long insert(T t);/** * 通过id删除数据 * * @param id */public int delete(Serializable id);/** * 通过id更新数据 * * @param t */public int update(T t);/** * 查询数据中所有数据 * * @return */public List<T> finadAll();/** * 创建表 */public void createTable();}在其实现类DaoImp.java

其部分代码

public abstract class DaoImp<T> implements Dao<T> {private SQLiteDatabase db;public DaoImp(DbHelper helper) {super();db = helper.getWritableDatabase();}@Overridepublic long insert(T t) {if (!isTableExists()) {return -1;}ContentValues values = new ContentValues();fillContentValues(t, values);// 第一个参数标示数据的来源;第二个参数设置给谁// 此处省略n行代码return db.insert(getTableName(), null, values);}@Overridepublic int delete(Serializable id) {if (!isTableExists()) {return -1;}return db.delete(getTableName(), getIdName(null) + "=?",new String[] { id.toString() });}@Overridepublic int update(T t) {if (!isTableExists()) {return -1;}ContentValues values = new ContentValues();fillContentValues(t, values);return db.update(getTableName(), values, getIdName(t) + "=?",new String[] { getId(t) });}

在创建表的时候,如果此表已经存在,那么就不需要创建,否则就创建此表public boolean isTableExists() {String sql = "select count(*) as c from sqlite_master where type ='table' and name ='"+ getTableName() + "';";Cursor cursor = db.rawQuery(sql, null);if (cursor.moveToNext()) {int count = cursor.getInt(0);if (count > 0) {return true;}}return false;}这是查询数据库中所有的表,看指定的表是否存在。

通过bean创建表,使用的注解使实体类和表中列一一对应起来。

指定表名的注解

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface TableName {String value();}

指定表主键id注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface TableId {String value();boolean isAutoIncrease();}指定列注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Column {String value();}下面以一个Book.java实体类为示例,看看这些自定义注解的使用。@TableName("book")public class Book {@TableId(value = "serialnum", isAutoIncrease = true)@Column("serialnum")private int serialNum;@Column("name")private String name;@Column("des")private String des;public Book() {super();}public Book(String name, String des) {super();this.name = name;this.des = des;}public Book(int serialNum, String name, String des) {super();this.serialNum = serialNum;this.name = name;this.des = des;}public int getSerialNum() {return serialNum;}public void setSerialNum(int serialNum) {this.serialNum = serialNum;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDes() {return des;}public void setDes(String des) {this.des = des;}@Overridepublic String toString() {return "Book [serialNum=" + serialNum + ", name=" + name + ", des="+ des + "]";}}在DaoImpl.java中创建表@Overridepublic void createTable() {String tableName = getTableName();if (TextUtils.isEmpty(tableName)) {return;}if (isTableExists()) {return;}Map<String, String> columns = columnNames();StringBuffer sb = new StringBuffer();sb.append("CREATE TABLE ");sb.append(tableName);sb.append("(");boolean flag = true;if (columns != null) {Set<String> keySet = columns.keySet();Iterator<String> iterator = keySet.iterator();while (iterator.hasNext()) {String name = iterator.next();String type = columns.get(name);if (flag) {sb.append(name).append(" ").append(type);flag = false;} else {sb.append(",").append(name).append(" ").append(type);}}}sb.append(")");db.execSQL(sb.toString());}获取列明和列类型map。public Map<String, String> columnNames() {Map<String, String> columns = null;T t = getInstance();Field[] fields = t.getClass().getDeclaredFields();columns = new HashMap<String, String>();for (Field field : fields) {field.setAccessible(true);Column columAn = field.getAnnotation(Column.class);if (columAn != null) {TableId idAn = field.getAnnotation(TableId.class);if (idAn != null) {if (idAn.isAutoIncrease()) {columns.put(idAn.value(),"integer primary key autoincrement");} else {columns.put(idAn.value(), "varchar(50)");}} else {columns.put(columAn.value(), "varchar(50)");}}}return columns;}通过获取实体类中注解的类型,通过field.getAnnotation(Column.class);获取字段上的注解,如果是Column是列,获取其值,就是列名称。如果是TableId表示表的主键,其值就是是否自定增长。出门走好路,出口说好话,出手做好事。

使用注解和反射构建通用数据库框架

相关文章:

你感兴趣的文章:

标签云: