学习笔记-泛型的使用:通用数据库增删改查

利用泛型,得到一个通用的数据库工具类,进行增删改查

要解决的问题: 
 * 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);
		
	}

}
不用再重新写增删改查了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值