转载请注明出处: http://blog.csdn.net/forwardyzk/article/details/43673577
下面我们写一个操作数据库框架的示例,从而熟悉注解,反射,泛型的使用。
通过实体类创建和删除操作,因为操作数据库中的表不同,那么对应的实体类也不同,我们需要使用泛型来指定操作的实体类。使用注解使实体类和数据库表列一一对应。
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); } @Override public void onCreate(SQLiteDatabase db) { } @Override public 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(); }
其部分代码
public abstract class DaoImp<T> implements Dao<T> { private SQLiteDatabase db; public DaoImp(DbHelper helper) { super(); db = helper.getWritableDatabase(); } @Override public long insert(T t) { if (!isTableExists()) { return -1; } ContentValues values = new ContentValues(); fillContentValues(t, values);// 第一个参数标示数据的来源;第二个参数设置给谁 // 此处省略n行代码 return db.insert(getTableName(), null, values); } @Override public int delete(Serializable id) { if (!isTableExists()) { return -1; } return db.delete(getTableName(), getIdName(null) + "=?", new String[] { id.toString() }); } @Override public 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(); }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface TableId { String value(); boolean isAutoIncrease(); }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String value(); }
@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; } @Override public String toString() { return "Book [serialNum=" + serialNum + ", name=" + name + ", des=" + des + "]"; } }在DaoImpl.java中创建表
@Override public 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()); }
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; }
获取表名
/** * 获取表名字 * * @return */ public String getTableName() { T t = getInstance(); TableName tableName = t.getClass().getAnnotation(TableName.class); if (tableName != null) { return tableName.value(); } return null; }
创建实体类对象。
/** * 创建实体的对象 * * @return */ public T getInstance() { Class clazz = getClass();// 正在运行 Type genericSuperclass = clazz.getGenericSuperclass();// 获取支持泛型的父类 if (genericSuperclass instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass) .getActualTypeArguments(); Class target = (Class) actualTypeArguments[0]; try { return (T) target.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
在插入数据时候,通过传入bean对象,然后向对应的列中插入数据。
private void fillContentValues(T m, ContentValues values) { Field[] fields = m.getClass().getDeclaredFields(); for (Field item : fields) { item.setAccessible(true);// 施暴 Column column = item.getAnnotation(Column.class); if (column != null) { TableId id = item.getAnnotation(TableId.class); if (id != null) { // 主键+自增 if (id.isAutoIncrease()) { // 不需要设置数据到ContentValues } else { String key = column.value(); try { String value = item.get(m).toString();// m.field values.put(key, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } else { String key = column.value(); try { String value = item.get(m).toString();// m.field values.put(key, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } }
在这里还判断是主键注解TableId,如果是自增,那么不需要添加到values中,否则就向正常的列一样,也要添加到values中。
private void fillFields(Cursor cursor, T m) { Field[] fields = m.getClass().getDeclaredFields(); for (Field item : fields) { item.setAccessible(true); Column column = item.getAnnotation(Column.class); if (column != null) { String columnName = column.value(); int columnIndex = cursor.getColumnIndex(columnName); String value = cursor.getString(columnIndex); // 主键+自增:int long if (item.getType() == int.class) { try { item.set(m, Integer.parseInt(value)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } else if (item.getType() == long.class) { try { item.set(m, Long.parseLong(value)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } else { try { item.set(m, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } }
获取bean中的Column注解,然后获取其值(类名),通过columnvalue=cursor.getColumnIndex(columnName)获取此列在游标中的值,然后通过field.set(bean,columnvalue),设置给传进来的bean对象字段值。
private String getId(T t) { if (t == null) { t = getInstance(); } Field[] fields = t.getClass().getDeclaredFields(); for (Field item : fields) { item.setAccessible(true); TableId id = item.getAnnotation(TableId.class); if (id != null) { try { return item.get(t).toString(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } return null; }
下面介绍一个使用步骤:
BookImpl.java
public class BookImpl extends DaoImp<Book> { public BookImpl(DbHelper helper) { super(helper); } }
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/create_table" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="创建表" /> <Button android:id="@+id/find_all" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="查询" /> <Button android:id="@+id/insert" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="插入" /> <Button android:id="@+id/update" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="修改" /> <Button android:id="@+id/delete" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="删除" /> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="wrap_content" /> </ScrollView> </LinearLayout>
public class MainActivity extends Activity implements OnClickListener { private DaoImp<Book> bookDao; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); DbHelper helper = new DbHelper(MainActivity.this); bookDao = new BookImpl(helper); } private void initView() { Button create_table = (Button) findViewById(R.id.create_table); create_table.setOnClickListener(this); Button delete = (Button) findViewById(R.id.delete); delete.setOnClickListener(this); Button update = (Button) findViewById(R.id.update); update.setOnClickListener(this); Button insert = (Button) findViewById(R.id.insert); insert.setOnClickListener(this); Button find_all = (Button) findViewById(R.id.find_all); tv = (TextView) findViewById(R.id.tv); find_all.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.create_table: createTable(); break; case R.id.find_all: findAll(); break; case R.id.insert: insert(); break; case R.id.delete: delete(); break; case R.id.update: update(); break; default: break; } } private void update() { bookDao.update(new Book(1, "updateName", "updateDes")); } private void delete() { bookDao.delete(2); } private void insert() { Book b1 = new Book("第一本", "第一本描述"); Book b2 = new Book("第二本", "第二本描述"); Book b3 = new Book("第三本", "第三本描述"); bookDao.insert(b1); bookDao.insert(b2); bookDao.insert(b3); } private void findAll() { List<Book> finadAll = bookDao.finadAll(); StringBuffer sb = new StringBuffer(); tv.setText(""); if (finadAll != null) { for (Book book : finadAll) { sb.append(book.toString()).append(" \n "); } tv.setText(sb.toString()); } } private void createTable() { bookDao.createTable(); } }
DaoImp<Book> bookDao = new BookImpl(helper);获取book表操作类
bookDao.createTable();创建表
bookDao.insert(b3);插入一条记录
bookDao.delete(2);删除id为2的记录
bookDao.update(new Book(1, "updateName", "updateDes"));更新id为1的记录。
源码下载: http://download.csdn.net/detail/forwardyzk/8437161
效果图: