利用泛型,得到一个通用的数据库工具类,进行增删改查
要解决的问题:
* 1.表名的获取
* 2.将实体的数据按照对应关系导入到数据库表中
* 3.将数据表中列的数据按照对应关系导入到实体中
* 4.明确实体中的主键,获取到主键中封装的值
* 5.实体的对象创建
/**
* 实体操作的通用接口
* @author lenov0
*
*/
public interface Dao<M> {
long insert(M m);
int delete(Serializable id); //可实现int long String
int update(M m);
List<M> findAll();
}
//实现上面的接口
public abstract class DaoSupport<M> implements Dao<M>{
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>protected Context context;
<span style="white-space:pre"> </span>protected DBHelper helper;
<span style="white-space:pre"> </span>protected SQLiteDatabase db;
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>public DaoSupport(Context context) {
<span style="white-space:pre"> </span>super();
<span style="white-space:pre"> </span>this.context = context;
<span style="white-space:pre"> </span>helper = new DBHelper(context);
<span style="white-space:pre"> </span>db = helper.getWritableDatabase();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 增
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public long insert(M m) {
<span style="white-space:pre"> </span>ContentValues values = new ContentValues();
<span style="white-space:pre"> </span>fillColumn(m, values);
<span style="white-space:pre"> </span>return db.insert(getTableName(), null, values);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 删
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public int delete(Serializable id) {
<span style="white-space:pre"> </span>return db.delete(getTableName(), DBHelper.TABLE_ID + "=?", new String[]{id+""});
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 改
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public int update(M m) {
<span style="white-space:pre"> </span>ContentValues values = new ContentValues();
<span style="white-space:pre"> </span>fillColumn(m, values);
<span style="white-space:pre"> </span>return db.update(getTableName(), values, DBHelper.TABLE_ID + "=?", new String[]{getId(m)});
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 查
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public List<M> findAll() {
<span style="white-space:pre"> </span>List<M> result = null;
<span style="white-space:pre"> </span>Cursor cursor = db.query(DBHelper.TABLE_NEWS_NAME, null, null, null, null, null, null);
<span style="white-space:pre"> </span>if(cursor != null) {
<span style="white-space:pre"> </span>result = new ArrayList<M>();
<span style="white-space:pre"> </span>while(cursor.moveToNext()){
//<span style="white-space:pre"> </span>M m = new M();
//<span style="white-space:pre"> </span>String title = cursor.getString(cursor.getColumnIndex(DBHelper.TABLE_NEWS_TITLE));
//<span style="white-space:pre"> </span>news.setTitle(title);
<span style="white-space:pre"> </span>M m = getInstance();
<span style="white-space:pre"> </span>fillField(cursor, m);
<span style="white-space:pre"> </span>result.add(m);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>cursor.close();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return result;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 1.获取表名:利用注解Annotation
<span style="white-space:pre"> </span> * @return
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>private String getTableName() {
<span style="white-space:pre"> </span>//获取实体
<span style="white-space:pre"> </span>M m = getInstance();
<span style="white-space:pre"> </span>//根据注解里value值获取表名
<span style="white-space:pre"> </span>TableName annotation = m.getClass().getAnnotation(TableName.class);
<span style="white-space:pre"> </span>//如果需要在运行的时候获取注解,设置存活时间
<span style="white-space:pre"> </span>if(annotation != null){
<span style="white-space:pre"> </span>return annotation.value();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return "";
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 创建实体对象
<span style="white-space:pre"> </span> * @return
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public M getInstance() {
<span style="white-space:pre"> </span>//1哪个孩子在运行
<span style="white-space:pre"> </span>Class clazz = getClass(); //返回的是运行的class,this和super都一样
<span style="white-space:pre"> </span>//2获取该孩子的父类-“支持泛型”的父类
<span style="white-space:pre"> </span>//clazz.getSuperclass();这个方法没有泛型,用下面这个方法
<span style="white-space:pre"> </span>Type superClass = clazz.getGenericSuperclass();
<span style="white-space:pre"> </span>//泛型实现接口(参数化类型),规定了泛型的通用操作
<span style="white-space:pre"> </span>if(superClass != null && superClass instanceof ParameterizedType) {
<span style="white-space:pre"> </span>//3获取到泛型中的参数
<span style="white-space:pre"> </span>Type[] arguments = ((ParameterizedType)superClass).getActualTypeArguments();
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>return (M) ((Class)arguments[0]).newInstance();
<span style="white-space:pre"> </span>} catch (InstantiationException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>} catch (IllegalAccessException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>return null;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 实体数据填充到数据库列
<span style="white-space:pre"> </span> * @param m 数据源
<span style="white-space:pre"> </span> * @param values 导入的目标
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>private void fillColumn(M m, ContentValues values) {
<span style="white-space:pre"> </span>//m.getClass().getFields();
<span style="white-space:pre"> </span>Field[] fields = m.getClass().getDeclaredFields(); //获取字段
<span style="white-space:pre"> </span>for (Field field : fields) {
<span style="white-space:pre"> </span>field.setAccessible(true);
<span style="white-space:pre"> </span>Column column = field.getAnnotation(Column.class);
<span style="white-space:pre"> </span>if(column != null) {
<span style="white-space:pre"> </span>String key = column.value(); //得到列名
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>//得到实体的值
<span style="white-space:pre"> </span>String value = field.get(m).toString();//Returns the value of the field in the specified object.
<span style="white-space:pre"> </span>//注意是不是主键,且主键是否自增
<span style="white-space:pre"> </span>ID id = field.getAnnotation(ID.class);
<span style="white-space:pre"> </span>if(id != null && id.autoincrement()) {
<span style="white-space:pre"> </span>//就不给主键赋值,不然主键都是0了
<span style="white-space:pre"> </span>} else {
<span style="white-space:pre"> </span>values.put(key, value);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>} catch (IllegalAccessException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>} catch (IllegalArgumentException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 数据库数据填充到实体
<span style="white-space:pre"> </span> * @param cursor 数据库数据
<span style="white-space:pre"> </span> * @param m 待填充实体
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>private void fillField(Cursor cursor, M m) {
<span style="white-space:pre"> </span>Field[] fields = m.getClass().getDeclaredFields();
<span style="white-space:pre"> </span>for (Field field : fields) {
<span style="white-space:pre"> </span>field.setAccessible(true);
<span style="white-space:pre"> </span>//拿到field的注解
<span style="white-space:pre"> </span>Column column = field.getAnnotation(Column.class);
<span style="white-space:pre"> </span>if(column != null) {
<span style="white-space:pre"> </span>//拿到数据库列的数据
<span style="white-space:pre"> </span>String value = cursor.getString(cursor.getColumnIndex(column.value()));
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>//若返回的是int类型
<span style="white-space:pre"> </span>if(field.getType() == int.class) {
<span style="white-space:pre"> </span>field.set(m, Integer.valueOf(value));
<span style="white-space:pre"> </span>} else {
<span style="white-space:pre"> </span>field.set(m, value);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>} catch (IllegalAccessException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>} catch (IllegalArgumentException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 获取主键
<span style="white-space:pre"> </span> * @return
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>private String getId(M m) {
<span style="white-space:pre"> </span>Field[] fields = m.getClass().getDeclaredFields();
<span style="white-space:pre"> </span>for (Field field : fields) {
<span style="white-space:pre"> </span>field.setAccessible(true);
<span style="white-space:pre"> </span>ID id = field.getAnnotation(ID.class);
<span style="white-space:pre"> </span>if(id != null) {
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>return field.get(m).toString();
<span style="white-space:pre"> </span>} catch (IllegalAccessException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>} catch (IllegalArgumentException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return null;
<span style="white-space:pre"> </span>}
}
/**
* 指定实体Field与数据库中列的对应关系
* @author lenov0
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
/**
* 列名
* @return
*/
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ID {
boolean autoincrement();
}
/**
* 指定实体与数据库中表的对应关系
* @author lenov0
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
/**
* 表名
* @return
*/
String value();
}
数据库建立:
public class DBHelper extends SQLiteOpenHelper {
public static int VERSION = 1;
public static final String NAME = "itgn.db";
public static final String TABLE_ID = "_id";
public static final String TABLE_NEWS_NAME = "news";
public static final String TABLE_NEWS_TITLE = "title";
public static final String TABLE_NEWS_SUMMARY = "summary";
//新闻表:主键+标题+摘要
public DBHelper(Context context) {
super(context, NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NEWS_NAME + " (" +
TABLE_ID + " integer primary key autoincrement, " +
TABLE_NEWS_TITLE + " varchar(50), " +
TABLE_NEWS_SUMMARY + " varchar(200))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
bean:
/**
* 新闻实体
* @author lenov0
*
*/
@TableName(DBHelper.TABLE_NEWS_NAME)
public class News {
@ID(autoincrement=true)
@Column(DBHelper.TABLE_ID)
private int id;
@Column(DBHelper.TABLE_NEWS_TITLE)
private String title;
@Column(DBHelper.TABLE_NEWS_SUMMARY)
private String summary;
public int getId() {
return id;
}
public String getTitle() {
return title;
}
public String getSummary() {
return summary;
}
public void setId(int id) {
this.id = id;
}
public void setTitle(String title) {
this.title = title;
}
public void setSummary(String summary) {
this.summary = summary;
}
}
/**
* 依靠建立通用DAO,增删改查都在DaoSupport中实现,不用写了
*
* @author lenov0
*
*/
public class NewsDaoImpl extends DaoSupport<News> implements NewsDao {
public NewsDaoImpl(Context context) {
super(context);
}
}
不用再重新写增删改查了。