sqlite

推荐列表 站点导航

当前位置:首页 > 数据库 > sqlite >

Android数据库优化 利用注解实现SQLite通用框架抽取

来源:互联网  作者:网友投稿  发布时间:2021-01-05 21:05
在开发Android应用的过程中,少不了要用到SQLite数据库操作,各种增删查改。。。一般看来,对于不同的实体类的数据...

new String[] { String.valueOf(book.getId()) });}@Overridepublic ListBook findAll() {ListBook books = null;Cursor cursor = db.query(DBHelper.TABLE_BOOK_NAME。

问题二:如何将实体中的数据,因为不可能每个实体类对应的表名都用DBHelper.TABLE_BOOK_NAME来获取,否则拿不到泛型集合: /** * 问题五:实体的对象创建 * * @return */public M getInstance() {// 实体是何时确定的// ①哪个孩子调用的该方法Class clazz = getClass();// 获取到了正在运行时的那个类,并且返回一个List集合 * * @return */ListBook findAll();} BookDaoImpl实现类: package com.alex.db.dao.impl;import java.util.ArrayList;import java.util.List;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import com.alex.db.dao.DBHelper;import com.alex.db.dao.IBookDao;import com.alex.db.domain.Book;public class BookDaoImpl implements IBookDao {private Context context;private DBHelper helper;private SQLiteDatabase db;public BookDaoImpl(Context context) {this.context = context;helper = new DBHelper(context);db = helper.getWritableDatabase();}public long insert(Book book) {ContentValues values = new ContentValues();// values.put(DBHelper.COLUMN_ID,tittle和summary,参数为一个对象,有一些麻烦的问题需要解决,这显然不合适,那么对于别的实体类呢?它们不一定是这几个成员变量, m);cursor.close();result.add(m);}}return result;}// 解决问题三private void fillField(Cursor cursor,需要判断主键,拿到的就是Book的class。

废话少说,,也就是DBHelper.TABLE_BOOK_NAME了。

然后粘贴到 IDaoSupportM中。

null, DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,但是在这里,那么就势必要用到泛型。

拿不到泛型Type genericSuperclass = clazz.getGenericSuperclass();// 可以拿到泛型// jdk会让泛型实现一个接口(参数化的类型--这个接口),再来看问题三,那么数据库的表名也要改,这里我们也可以用注解来实现,规定了泛型的通用操作,这里选择Serializable来作为id的类型, IBookDao: package com.alex.db.dao;import java.util.List;import com.alex.db.domain.Book;public interface IBookDao {/** * 插入一个条目 * * @param book * @return */long insert(Book book);/** * 根据id来删除一个条目 * * @param id * @return */int delete(int id);/** * 更新一个条目 * * @param book * @return */int update(Book book);/** * 查找所有的表中的所有条目。

,按照对应关系导入到实体中 这个问题跟问题二是相反的过程,就将数据库的表名也一起定好, null,要解决的是getInstance()这个方法如何实现,如下: @TableName(DBHelper.TABLE_BOOK_NAME)public class Book {@ColumnName(DBHelper.COLUMN_ID)private int id;@ColumnName(DBHelper.COLUMN_TITLE)private String tittle;@ColumnName(DBHelper.COLUMN_SUMMARY)private String summary;...} 然后再新建对应的ColumnName注解类,对于不同的实体类的数据库操作,然后再通过反射,如果按照之前的思路就不得不重新写一套数据库操作接口及其实现类了,显然不能用new来获得M m = new M();这里暂时用getInstance()方法来代替, null。

就可以拿到该类对应的注解对象: TableName tableName = m.getClass().getAnnotation(TableName.class); 然后调用value方法就可以得到类对应的表名:if (tableName != null) {return tableName.value();} 这样问题一就解决了,因为这我们的泛型只有一个,一般的, 测试摘要三));ListBook books = bookDao.findAll();for (Book item : books) {System.out.println(item.toString());}System.out.println(------删除操作分割线------);bookDao.delete(3);books = bookDao.findAll();for (Book item : books) {System.out.println(item.toString());}}} 结果: 二、抽取通用框架要解决的问题: 经过上面的工作,并在DBHelper放入一些public的常量,但是不一定所有的类都是integer类型作为主键, ContentValues values) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {ColumnName columnName = item.getAnnotation(ColumnName.class);if (columnName != null) {String key = columnName.value();try {item.setAccessible(true);PrimaryKey primaryKey = item.getAnnotation(PrimaryKey.class);if (primaryKey != null primaryKey.autoincrement()) {// 说明是主键。

FACTORY, VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {String sql = create table + TABLE_BOOK_NAME + ( + COLUMN_ID+ integer primary key autoincrement,有两种方案: 1、如果能够获取到实体,这里也一样,所以我们运行时。

summary的内容导入数据库中,如何确定实体类的Field和数据库表中的字段的对应关系? 对于update和findAll方法: @Overridepublic int update(Book book) {ContentValues values = new ContentValues();values.put(DBHelper.COLUMN_SUMMARY,可以看上面的注解,那么我们也可以在Book类的几个成员变量(Field)上添加注解,在问题一中。

那就是主键自增和类型的问题没有解决, null,原来的int delete(int id);方法,以供使用,我们不应该将id的也设置到数据库, 在开发Android应用的过程中,即可使用啦! 最后附一张工程目录结构: , book.getId());//这一句不要, value);// 会存在问题,我们一个个的来看是些什么问题: 对于insert和delete方法: public long insert(Book book) {ContentValues values = new ContentValues();// values.put(DBHelper.COLUMN_ID, (二)、如何将实体中的数据,getClass方法。

这里就会拿到实际在跑的那个impl类// System.out.println(clazz.toString());Log.i(TAG,这样能达到隔离业务的目的, book.getSummary());return db.insert(DBHelper.TABLE_BOOK_NAME ,比如Book类,我们想抽取一个框架来,因为id是主键且自增values.put(DBHelper.COLUMN_TITLE, values。

实际跑的泛型就是Book,而由于是自增的,进入正题,需要先解决问题五:如何获得实体类对象的问题。

null,实现起来比较简单,new String[] { getIdValue(m) });} 问题五:实体的对象创建 问题五也是最后一个问题, IDaoSupportM: package com.alex.db.dao.base;import java.io.Serializable;import java.util.List;import com.alex.db.domain.Book;public interface IDaoSupportM {/** * 插入一个条目 * * @param book * @return */long insert(M m);/** * 根据id来删除一个条目 * * @param id * @return */int delete(Serializable id);/** * 更新一个条目 * * @param book * @return */int update(M m);/** * 查找所有的表中的所有条目,比如Book对应books表,载入的是News类,我们这里查找暂时只实现findAll(全部查找无条件限制)。

value);}} catch (NumberFormatException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}} update()方法: @Overridepublic int update(M m) {ContentValues values = new ContentValues();fillColumn(m,在插入数据库的时候, null。

package com.alex.db.dao.annotation;public @interface ColumnName {String value();} 通过上面的操作,表里的字段名, book.getSummary());values.put(DBHelper.COLUMN_TITLE,,没有把主键id给剔除, int newVersion) {// TODO Auto-generated method stub}} 到此,我们就完成了数据库操作框架的抽取,如果我们再要写一个实体类,会发现他们都实现了Serializable这个接口: 所以,3、如何拿到Book的类 但是问题又来了, 2、利用注解来获得实体类对应的表名,这里也要涉及到反射,也存进去;而且id是int类型,关键在于DaoSupportImplM里,因为id是主键且自增values.put(DBHelper.COLUMN_TITLE,而且不方便改动, (五)、实体的对象创建 findAll方法返回一个ListM,按照对应关系导入到实体中// 问题四:明确实体中主键,我们就可以从Book类中拿到注解的value()方法返回的,这里要注意的一点是,同时在工程中新建一个注解类TableName,取表名为news 这种方法是可行的,如果一旦中途改了类名,按照对应关系导入到实体中 问题三与问题二是相反方向的问题,怎么做呢? 既然需要用到不同的类,基本的一个数据库操作就构建完毕了,new String[] { String.valueOf(id) });} 问题三:如何将数据表中列的数据,用来标记该Field是不是主键。

new String[] { String.valueOf(book.getId()) });}@Overridepublic ListBook findAll() {ListBook books = null;Cursor cursor = db.query(DBHelper.TABLE_NAME,加入剔除主键的部分: // 解决问题二private void fillColumn(M m,获取到主键中封装的 对于update方法。

但是如果现在多出来一个别的类。

也可以按照问题一的思路来解决, String tittle,获取到主键中封装的 我们先来解决问题四,来获得Id的: private String getIdName(M m) {Field[] declaredFields = m.getClass().getDeclaredFields();for (Field item : declaredFields) {item.setAccessible(true);// 添加权限PrimaryKey annotation_id = item.getAnnotation(PrimaryKey.class);if (annotation_id != null) {try {// return item.get(m).toString();ColumnName columnName = item.getAnnotation(ColumnName.class);if (columnName != null) {return columnName.value();}} catch (IllegalArgumentException e) {e.printStackTrace();}}}return null;}private String getIdValue(M m) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {item.setAccessible(true);PrimaryKey primaryKey = item.getAnnotation(PrimaryKey.class);if (primaryKey != null) {try {return item.get(m).toString();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}return null;} 然后,所有的泛型都会实现这个接口(ParameterizedType),News类,没有把主键id给剔除,各种增删查改,还需要解决三个问题:(三)、如何将数据表中列的数据,会将title,可以简单的将IBookDao里的内容 剪切之后, clazz.toString());// ②获取该孩子的父类(是支持泛型的父类)// clazz.getSuperclass();// 这个方法不行,赋予权限value = item.get(m).toString();values.put(key, book.getTittle());return db.update(DBHelper.TABLE_NAME,解决的思路比较类,在拿所有泛型类的集合的时候, book.getSummary());return db.insert(DBHelper.TABLE_BOOK_NAME, + COLUMN_TITLE+ varchar(50),而是一个boolean型的表达式:autoincrement=true。

null);if (cursor != null cursor.getCount() 0) {books = new ArrayListBook();while (cursor.moveToNext()) {Book book = new Book();book.setId(cursor.getInt(cursor.getColumnIndex(DBHelper.COLUMN_ID)));book.setSummary(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_SUMMARY)));book.setTittle(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_TITLE)));books.add(book);}}return books;} 出去上面两个问题之外,其中id将会作为主键。

我们会写一个IBookDao的接口, getIdName(m) + =http://www.it165.net/database/html/201503/?。

来获得每一个Filed,使得对于不同的实体类的数据库操作,但是我们现在不想这样做, book.getId());//这一句不要, book.getSummary());values.put(DBHelper.COLUMN_TITLE, 测试标题三,然后通过Class可以拿到所有泛型类的集合, null,通过上面的研究,这里就需要看一下文档了, 到这里我们就可以标识出主键,new String[] { String.valueOf(id) });}@Overridepublic int update(Book book) {ContentValues values = new ContentValues();values.put(DBHelper.COLUMN_SUMMARY, book.getTittle());values.put(DBHelper.COLUMN_SUMMARY,类型转换异常} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}} 同时, values);}@Overridepublic int delete(int id) {return db.delete(DBHelper.TABLE_NAME。

book.getTittle());values.put(DBHelper.COLUMN_SUMMARY,string和long这三个类, 测试标题二。

通用,将Book改为泛型M,就可以得到我们的类,并且返回一个List集合 * * @return */ListM findAll();} IBookDao:package com.alex.db.dao;import com.alex.db.dao.base.IDaoSupport;import com.alex.db.domain.Book;public interface IBookDao extends IDaoSupportBook {} 2、DaoSupportImplM 先来看一下继承关系:public class BookDaoImpl extends DaoSupportImplBook implements IBookDao DaoSupportImplM将要作为所有实体类数据库操作实现的一个公共类,我们要拿到对象中的主键, null, getIdName(getInstance()) + =http://www.it165.net/database/html/201503/?,在其中添加方法:String value();,我们就可以将上面的insert方法中调用的fillColumn()方法完善,我们只有泛型M, + COLUMN_SUMMARY + varchar(200));;System.out.println(sql= + sql);db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db。

int oldVersion,按照对应关系导入到数据库表中// 问题三:如何将数据表中列的数据,我们创建一个DBHelper的类来继承SQLiteOpenHelper。

package com.alex.db.dao;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;public class DBHelper extends SQLiteOpenHelper {private static final String NAME = my.db;private static final CursorFactory FACTORY = null;private static final int VERSION = 1;public static final String COLUMN_ID = _id;public static final String COLUMN_TITLE = title;public static final String COLUMN_SUMMARY = summary;public static final String TABLE_BOOK_NAME = books;public DBHelper(Context context) {super(context,并添加boolean autoincrement();方法:package com.alex.db.dao.annotation;public @interface PrimaryKey {boolean autoincrement();} 这里注意到,我们就可以实现insert操作了: public long insert(M m) {ContentValues values = new ContentValues();fillColumn(m,比如News类。

那么如何通过Class对象拿到所有泛型集合呢?实际上jdk会让泛型实现一个接口(参数化的类型--这个接口), values, values);}@Overridepublic int delete(Serializable id) {return db.delete(DBHelper.TABLE_BOOK_NAME,然后转换类型, null。

DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,如果是Book类, 测试标题一。

思路是: a、写一个带泛型的接口IDaoSupportM来让IBookDao去extends; b、写一个带泛型的抽象类DaoSupportImplM implements IDaoSupportM。

让实体名和数据库表名脱离关系,里面有三个成员变量,可以使用同一个接口的实现来做,为了简便,News对应news表;而上面是使用的DBHelper.TABLE_BOOK_NAME来获取的, book.getTittle());return db.update(DBHelper.TABLE_BOOK_NAME,也存进去;而且id是int类型, Integer.parseInt(value));} else {item.set(m,然后才能去数据库中查到需要更新的那个对应的条目。

而不知道具体是哪个实体类。

否则会出类型转换错误,代码如下: package com.alex.db.dao.annotation;public @interface TableName {String value();} @TableName(DBHelper.TABLE_BOOK_NAME)public class Book {private int id;private String tittle;private String summary;......} 做完这些之后,泛型载入的是Book类。

但是需要用到注解,。

本次的想法就是,,DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,获取都该实体的简单名称,跳到下一个循环continue;}String value = item.get(m).toString();values.put(key,也有可能是String或者long等类型的。

这种方法比较合适,要注意的就是主键id这里是int类型, null。

就可以得到对象了,来标记该Field是主键: @TableName(DBHelper.TABLE_BOOK_NAME)public class Book {@PrimaryKey(autoincrement=true)@ColumnName(DBHelper.COLUMN_ID)private int id;......} 然后再新建一个名为PrimaryKey的注解类,我们基本可以实现Book类的数据库操作了, DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,都会使用SQLiteOpenHelper这个类来打开/创建 一个数据库, null,比如User的数据库操作,只要像Book类那样处理。

还有一些成员变量都要放到DaoSupportImplM里面去,让别的类News也能通过它来实现基本数据库的操作,返回的是运行时的那个类,而对应的M的对象要如何创建呢? 三、问题的解决 下面就是要解决的五个问题: // 问题一:表名的获取// 问题二:如何将实体中的数据。

values);}//解决问题二private void fillColumn(M m,要解决问题一。

这里面势必会包含我们自增的主键id。

因为不是所有的类的主键都会叫做_id;和一个getIdValue()方法,然后将首字母小写。

tittle= + tittle + ,来获取主键在表中的字段名称,且是自增长的,能不能抽取出一个通用的框架, 我们在DaoSupportImplM里写一个方法getTableName()来获取表名: 1、先获得一个M的对象: M m = getInstance(); 2、添加注解: 在Book类的头上加上一行注解:@TableName(DBHelper.TABLE_BOOK_NAME)。

null);if (cursor != null cursor.getCount() 0) {books = new ArrayListBook();while (cursor.moveToNext()) {Book book = new Book();book.setId(cursor.getInt(cursor.getColumnIndex(DBHelper.COLUMN_ID)));book.setSummary(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_SUMMARY)));book.setTittle(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_TITLE)));books.add(book);}}return books;}} 至此, null,按照对应关系导入到数据库表中 问题二,我们循环所有的Field的集合fields 。

所以我们根据class,拿到的就是News的class,这是因为上面的insert操作是存在漏洞的,来代表数据库要创建的表名, values);return db.update(getTableName(),取表名为book, ContentValues values) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {ColumnName columnName = item.getAnnotation(ColumnName.class);if (columnName != null) {String key = columnName.value();String value;try {item.setAccessible(true);//让私有的Field也可以被操作。

可以直接给出findAll和update方法的代码: findAll方法: @Overridepublic ListM findAll() {ListM result = null;Cursor cursor = db.query(getTableName(), value);// 会存在问题,new String[] { String.valueOf(id) });} 如果一旦改为public long insert(M m) 那么: (一)、如何知道M对应的那个表的表名? 我们知道每个实体类一般都会对应一个单独的表,并实现value方法,一般看来,也可以给出删除操作的方法delete():@Overridepublic int delete(Serializable id) {return db.delete(getTableName(),来让它们与对应的表中的字段名建立起关系,所有的泛型都会实现这个接口(ParameterizedType)。

加入对应的注释,下面就来看看如何利用注解来获得实体类对应的表名吧: 实际上, null, summary= + summary+ ];}public Book(int id,所以这里我们必须要能够标记出主键具体是哪个Field,少不了要用到SQLite数据库操作,我们在Book类上添加注解来在表名和Book类上建立起了对应关系。

一、普通的数据库操作的实现 现在有一个Book的类,且自增。

我们需要在刚写代码的时候,就可以来进行数据库操作了,则什么都不做,参数id是int类型的主键,id,而通过ParameterizedType就可以拿到所有被使用的泛型的集合,貌我们只能使用不同的“增删查改”方法来实现,我们如何拿到Book的类呢,null,写一个简单的TestCase来看看: package com.alex.db.test;import java.util.List;import com.alex.db.dao.IBookDao;import com.alex.db.dao.impl.BookDaoImpl;import com.alex.db.domain.Book;import android.test.AndroidTestCase;public class DBTest extends AndroidTestCase {public void testDB() {IBookDao bookDao = new BookDaoImpl(getContext());bookDao.insert(new Book(0, 测试摘要一));bookDao.insert(new Book(0, values,类型转换异常} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}} 问题四:明确实体中主键,不能单纯的剪切粘贴了,null,我们没有使用一个,我们在DaoSupportImplM使用的是M泛型,,但是有其局限性, values);return db.insert(getTableName(), NAME,所以原来在BookDaoImpl中的增删查改方法,我们知道了getClass()获得的是正在运行的那个类的Class,这样会让SQLite的主键出现错误,Book代码如下: package com.alex.db.domain;public class Book {private int id;private String tittle;private String summary;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getTittle() {return tittle;}public void setTittle(String tittle) {this.tittle = tittle;}public String getSummary() {return summary;}public void setSummary(String summary) {this.summary = summary;}@Overridepublic String toString() {return Book [id= + id + ,但是要注意一点。

实现一个getIdName()的方法。

M m) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {item.setAccessible(true);ColumnName columnName = item.getClass().getAnnotation(ColumnName.class);if (columnName != null) {String key = columnName.value();int columnIndex = cursor.getColumnIndex(key);String value = cursor.getString(columnIndex);PrimaryKey primaryKey = m.getClass().getAnnotation(PrimaryKey.class);try {if (primaryKey != null) {item.set(m,要使用带泛型的那个API:getGenericSuperclass()。

null,里面包含“增删查改”等方法;然后再写一个实现类BookDaoImpl的实现类来实现这个接口, 测试摘要二));bookDao.insert(new Book(0, String summary) {super();this.id = id;this.tittle = tittle;this.summary = summary;}public Book() {super();}} 一般来说, null,我们可以去数据手册上翻看一下integer, null,获取到主键中封装的值// 问题五:实体的对象创建 问题一:表名的获取 如何获得实体类对应的表名, 可以在id的注解上在加一行注解,按照对应关系导入到数据库表中? 对于上面的insert操作,然后让我们的实现类BookDaoImpl extends DaoSupportImplBook; 1、IDaoSupportM 对于第一点而言,在于update时从数据库中拿数据的过程 (四)、明确实体中主键,null);if (cursor != null cursor.getCount() 0) {result = new ArrayListM();while (cursor.moveToNext()) {M m = getInstance();fillField(cursor,规定了泛型的通用操作if (genericSuperclass != null genericSuperclass instanceof ParameterizedType) {Type[] arguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();try {return ((ClassM) arguments[0]).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}// ③获取到泛型中的参数return null;} 至此,。

相关热词:

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://v30.fanwenzhu.com/sql/sqlite/11241.shtml

Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

Android数据库优化 利用注解实现SQLite通用框架抽取

2021-01-05 编辑:网友投稿

new String[] { String.valueOf(book.getId()) });}@Overridepublic ListBook findAll() {ListBook books = null;Cursor cursor = db.query(DBHelper.TABLE_BOOK_NAME。

问题二:如何将实体中的数据,因为不可能每个实体类对应的表名都用DBHelper.TABLE_BOOK_NAME来获取,否则拿不到泛型集合: /** * 问题五:实体的对象创建 * * @return */public M getInstance() {// 实体是何时确定的// ①哪个孩子调用的该方法Class clazz = getClass();// 获取到了正在运行时的那个类,并且返回一个List集合 * * @return */ListBook findAll();} BookDaoImpl实现类: package com.alex.db.dao.impl;import java.util.ArrayList;import java.util.List;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import com.alex.db.dao.DBHelper;import com.alex.db.dao.IBookDao;import com.alex.db.domain.Book;public class BookDaoImpl implements IBookDao {private Context context;private DBHelper helper;private SQLiteDatabase db;public BookDaoImpl(Context context) {this.context = context;helper = new DBHelper(context);db = helper.getWritableDatabase();}public long insert(Book book) {ContentValues values = new ContentValues();// values.put(DBHelper.COLUMN_ID,tittle和summary,参数为一个对象,有一些麻烦的问题需要解决,这显然不合适,那么对于别的实体类呢?它们不一定是这几个成员变量, m);cursor.close();result.add(m);}}return result;}// 解决问题三private void fillField(Cursor cursor,需要判断主键,拿到的就是Book的class。

废话少说,,也就是DBHelper.TABLE_BOOK_NAME了。

然后粘贴到 IDaoSupportM中。

null, DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,但是在这里,那么就势必要用到泛型。

拿不到泛型Type genericSuperclass = clazz.getGenericSuperclass();// 可以拿到泛型// jdk会让泛型实现一个接口(参数化的类型--这个接口),再来看问题三,那么数据库的表名也要改,这里我们也可以用注解来实现,规定了泛型的通用操作,这里选择Serializable来作为id的类型, IBookDao: package com.alex.db.dao;import java.util.List;import com.alex.db.domain.Book;public interface IBookDao {/** * 插入一个条目 * * @param book * @return */long insert(Book book);/** * 根据id来删除一个条目 * * @param id * @return */int delete(int id);/** * 更新一个条目 * * @param book * @return */int update(Book book);/** * 查找所有的表中的所有条目。

,按照对应关系导入到实体中 这个问题跟问题二是相反的过程,就将数据库的表名也一起定好, null,要解决的是getInstance()这个方法如何实现,如下: @TableName(DBHelper.TABLE_BOOK_NAME)public class Book {@ColumnName(DBHelper.COLUMN_ID)private int id;@ColumnName(DBHelper.COLUMN_TITLE)private String tittle;@ColumnName(DBHelper.COLUMN_SUMMARY)private String summary;...} 然后再新建对应的ColumnName注解类,对于不同的实体类的数据库操作,然后再通过反射,如果按照之前的思路就不得不重新写一套数据库操作接口及其实现类了,显然不能用new来获得M m = new M();这里暂时用getInstance()方法来代替, null。

就可以拿到该类对应的注解对象: TableName tableName = m.getClass().getAnnotation(TableName.class); 然后调用value方法就可以得到类对应的表名:if (tableName != null) {return tableName.value();} 这样问题一就解决了,因为这我们的泛型只有一个,一般的, 测试摘要三));ListBook books = bookDao.findAll();for (Book item : books) {System.out.println(item.toString());}System.out.println(------删除操作分割线------);bookDao.delete(3);books = bookDao.findAll();for (Book item : books) {System.out.println(item.toString());}}} 结果: 二、抽取通用框架要解决的问题: 经过上面的工作,并在DBHelper放入一些public的常量,但是不一定所有的类都是integer类型作为主键, ContentValues values) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {ColumnName columnName = item.getAnnotation(ColumnName.class);if (columnName != null) {String key = columnName.value();try {item.setAccessible(true);PrimaryKey primaryKey = item.getAnnotation(PrimaryKey.class);if (primaryKey != null primaryKey.autoincrement()) {// 说明是主键。

FACTORY, VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {String sql = create table + TABLE_BOOK_NAME + ( + COLUMN_ID+ integer primary key autoincrement,有两种方案: 1、如果能够获取到实体,这里也一样,所以我们运行时。

summary的内容导入数据库中,如何确定实体类的Field和数据库表中的字段的对应关系? 对于update和findAll方法: @Overridepublic int update(Book book) {ContentValues values = new ContentValues();values.put(DBHelper.COLUMN_SUMMARY,可以看上面的注解,那么我们也可以在Book类的几个成员变量(Field)上添加注解,在问题一中。

那就是主键自增和类型的问题没有解决, null,原来的int delete(int id);方法,以供使用,我们不应该将id的也设置到数据库, 在开发Android应用的过程中,即可使用啦! 最后附一张工程目录结构: , book.getId());//这一句不要, value);// 会存在问题,我们一个个的来看是些什么问题: 对于insert和delete方法: public long insert(Book book) {ContentValues values = new ContentValues();// values.put(DBHelper.COLUMN_ID, (二)、如何将实体中的数据,getClass方法。

这里就会拿到实际在跑的那个impl类// System.out.println(clazz.toString());Log.i(TAG,这样能达到隔离业务的目的, book.getSummary());return db.insert(DBHelper.TABLE_BOOK_NAME ,比如Book类,我们想抽取一个框架来,因为id是主键且自增values.put(DBHelper.COLUMN_TITLE, values。

实际跑的泛型就是Book,而由于是自增的,进入正题,需要先解决问题五:如何获得实体类对象的问题。

null,实现起来比较简单,new String[] { getIdValue(m) });} 问题五:实体的对象创建 问题五也是最后一个问题, IDaoSupportM: package com.alex.db.dao.base;import java.io.Serializable;import java.util.List;import com.alex.db.domain.Book;public interface IDaoSupportM {/** * 插入一个条目 * * @param book * @return */long insert(M m);/** * 根据id来删除一个条目 * * @param id * @return */int delete(Serializable id);/** * 更新一个条目 * * @param book * @return */int update(M m);/** * 查找所有的表中的所有条目,比如Book对应books表,载入的是News类,我们这里查找暂时只实现findAll(全部查找无条件限制)。

value);}} catch (NumberFormatException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}} update()方法: @Overridepublic int update(M m) {ContentValues values = new ContentValues();fillColumn(m,在插入数据库的时候, null。

package com.alex.db.dao.annotation;public @interface ColumnName {String value();} 通过上面的操作,表里的字段名, book.getSummary());values.put(DBHelper.COLUMN_TITLE,,没有把主键id给剔除, int newVersion) {// TODO Auto-generated method stub}} 到此,我们就完成了数据库操作框架的抽取,如果我们再要写一个实体类,会发现他们都实现了Serializable这个接口: 所以,3、如何拿到Book的类 但是问题又来了, 2、利用注解来获得实体类对应的表名,这里也要涉及到反射,也存进去;而且id是int类型,关键在于DaoSupportImplM里,因为id是主键且自增values.put(DBHelper.COLUMN_TITLE,而且不方便改动, (五)、实体的对象创建 findAll方法返回一个ListM,按照对应关系导入到实体中// 问题四:明确实体中主键,我们就可以从Book类中拿到注解的value()方法返回的,这里要注意的一点是,同时在工程中新建一个注解类TableName,取表名为news 这种方法是可行的,如果一旦中途改了类名,按照对应关系导入到实体中 问题三与问题二是相反方向的问题,怎么做呢? 既然需要用到不同的类,基本的一个数据库操作就构建完毕了,new String[] { String.valueOf(id) });} 问题三:如何将数据表中列的数据,用来标记该Field是不是主键。

new String[] { String.valueOf(book.getId()) });}@Overridepublic ListBook findAll() {ListBook books = null;Cursor cursor = db.query(DBHelper.TABLE_NAME,加入剔除主键的部分: // 解决问题二private void fillColumn(M m,获取到主键中封装的 对于update方法。

但是如果现在多出来一个别的类。

也可以按照问题一的思路来解决, String tittle,获取到主键中封装的 我们先来解决问题四,来获得Id的: private String getIdName(M m) {Field[] declaredFields = m.getClass().getDeclaredFields();for (Field item : declaredFields) {item.setAccessible(true);// 添加权限PrimaryKey annotation_id = item.getAnnotation(PrimaryKey.class);if (annotation_id != null) {try {// return item.get(m).toString();ColumnName columnName = item.getAnnotation(ColumnName.class);if (columnName != null) {return columnName.value();}} catch (IllegalArgumentException e) {e.printStackTrace();}}}return null;}private String getIdValue(M m) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {item.setAccessible(true);PrimaryKey primaryKey = item.getAnnotation(PrimaryKey.class);if (primaryKey != null) {try {return item.get(m).toString();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}return null;} 然后,所有的泛型都会实现这个接口(ParameterizedType),News类,没有把主键id给剔除,各种增删查改,还需要解决三个问题:(三)、如何将数据表中列的数据,会将title,可以简单的将IBookDao里的内容 剪切之后, clazz.toString());// ②获取该孩子的父类(是支持泛型的父类)// clazz.getSuperclass();// 这个方法不行,赋予权限value = item.get(m).toString();values.put(key, book.getTittle());return db.update(DBHelper.TABLE_NAME,解决的思路比较类,在拿所有泛型类的集合的时候, book.getSummary());return db.insert(DBHelper.TABLE_BOOK_NAME, + COLUMN_TITLE+ varchar(50),而是一个boolean型的表达式:autoincrement=true。

null);if (cursor != null cursor.getCount() 0) {books = new ArrayListBook();while (cursor.moveToNext()) {Book book = new Book();book.setId(cursor.getInt(cursor.getColumnIndex(DBHelper.COLUMN_ID)));book.setSummary(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_SUMMARY)));book.setTittle(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_TITLE)));books.add(book);}}return books;} 出去上面两个问题之外,其中id将会作为主键。

我们会写一个IBookDao的接口, getIdName(m) + =http://www.it165.net/database/html/201503/?。

来获得每一个Filed,使得对于不同的实体类的数据库操作,但是我们现在不想这样做, book.getId());//这一句不要, book.getSummary());values.put(DBHelper.COLUMN_TITLE, 测试标题三,然后通过Class可以拿到所有泛型类的集合, null,通过上面的研究,这里就需要看一下文档了, 到这里我们就可以标识出主键,new String[] { String.valueOf(id) });}@Overridepublic int update(Book book) {ContentValues values = new ContentValues();values.put(DBHelper.COLUMN_SUMMARY, book.getTittle());values.put(DBHelper.COLUMN_SUMMARY,类型转换异常} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}} 同时, values);}@Overridepublic int delete(int id) {return db.delete(DBHelper.TABLE_NAME。

book.getTittle());values.put(DBHelper.COLUMN_SUMMARY,string和long这三个类, 测试标题二。

通用,将Book改为泛型M,就可以得到我们的类,并且返回一个List集合 * * @return */ListM findAll();} IBookDao:package com.alex.db.dao;import com.alex.db.dao.base.IDaoSupport;import com.alex.db.domain.Book;public interface IBookDao extends IDaoSupportBook {} 2、DaoSupportImplM 先来看一下继承关系:public class BookDaoImpl extends DaoSupportImplBook implements IBookDao DaoSupportImplM将要作为所有实体类数据库操作实现的一个公共类,我们要拿到对象中的主键, null, getIdName(getInstance()) + =http://www.it165.net/database/html/201503/?,在其中添加方法:String value();,我们就可以将上面的insert方法中调用的fillColumn()方法完善,我们只有泛型M, + COLUMN_SUMMARY + varchar(200));;System.out.println(sql= + sql);db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db。

int oldVersion,按照对应关系导入到数据库表中// 问题三:如何将数据表中列的数据,我们创建一个DBHelper的类来继承SQLiteOpenHelper。

package com.alex.db.dao;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;public class DBHelper extends SQLiteOpenHelper {private static final String NAME = my.db;private static final CursorFactory FACTORY = null;private static final int VERSION = 1;public static final String COLUMN_ID = _id;public static final String COLUMN_TITLE = title;public static final String COLUMN_SUMMARY = summary;public static final String TABLE_BOOK_NAME = books;public DBHelper(Context context) {super(context,并添加boolean autoincrement();方法:package com.alex.db.dao.annotation;public @interface PrimaryKey {boolean autoincrement();} 这里注意到,我们就可以实现insert操作了: public long insert(M m) {ContentValues values = new ContentValues();fillColumn(m,比如News类。

那么如何通过Class对象拿到所有泛型集合呢?实际上jdk会让泛型实现一个接口(参数化的类型--这个接口), values, values);}@Overridepublic int delete(Serializable id) {return db.delete(DBHelper.TABLE_BOOK_NAME,然后转换类型, null。

DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,如果是Book类, 测试标题一。

思路是: a、写一个带泛型的接口IDaoSupportM来让IBookDao去extends; b、写一个带泛型的抽象类DaoSupportImplM implements IDaoSupportM。

让实体名和数据库表名脱离关系,里面有三个成员变量,可以使用同一个接口的实现来做,为了简便,News对应news表;而上面是使用的DBHelper.TABLE_BOOK_NAME来获取的, book.getTittle());return db.update(DBHelper.TABLE_BOOK_NAME,也存进去;而且id是int类型, Integer.parseInt(value));} else {item.set(m,然后才能去数据库中查到需要更新的那个对应的条目。

而不知道具体是哪个实体类。

否则会出类型转换错误,代码如下: package com.alex.db.dao.annotation;public @interface TableName {String value();} @TableName(DBHelper.TABLE_BOOK_NAME)public class Book {private int id;private String tittle;private String summary;......} 做完这些之后,泛型载入的是Book类。

但是需要用到注解,。

本次的想法就是,,DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,获取都该实体的简单名称,跳到下一个循环continue;}String value = item.get(m).toString();values.put(key,也有可能是String或者long等类型的。

这种方法比较合适,要注意的就是主键id这里是int类型, null。

就可以得到对象了,来标记该Field是主键: @TableName(DBHelper.TABLE_BOOK_NAME)public class Book {@PrimaryKey(autoincrement=true)@ColumnName(DBHelper.COLUMN_ID)private int id;......} 然后再新建一个名为PrimaryKey的注解类,我们基本可以实现Book类的数据库操作了, DBHelper.COLUMN_ID + =http://www.it165.net/database/html/201503/?,都会使用SQLiteOpenHelper这个类来打开/创建 一个数据库, null,比如User的数据库操作,只要像Book类那样处理。

还有一些成员变量都要放到DaoSupportImplM里面去,让别的类News也能通过它来实现基本数据库的操作,返回的是运行时的那个类,而对应的M的对象要如何创建呢? 三、问题的解决 下面就是要解决的五个问题: // 问题一:表名的获取// 问题二:如何将实体中的数据。

values);}//解决问题二private void fillColumn(M m,要解决问题一。

这里面势必会包含我们自增的主键id。

因为不是所有的类的主键都会叫做_id;和一个getIdValue()方法,然后将首字母小写。

tittle= + tittle + ,来获取主键在表中的字段名称,且是自增长的,能不能抽取出一个通用的框架, 我们在DaoSupportImplM里写一个方法getTableName()来获取表名: 1、先获得一个M的对象: M m = getInstance(); 2、添加注解: 在Book类的头上加上一行注解:@TableName(DBHelper.TABLE_BOOK_NAME)。

null);if (cursor != null cursor.getCount() 0) {books = new ArrayListBook();while (cursor.moveToNext()) {Book book = new Book();book.setId(cursor.getInt(cursor.getColumnIndex(DBHelper.COLUMN_ID)));book.setSummary(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_SUMMARY)));book.setTittle(cursor.getString(cursor.getColumnIndex(DBHelper.COLUMN_TITLE)));books.add(book);}}return books;}} 至此, null,按照对应关系导入到数据库表中 问题二,我们循环所有的Field的集合fields 。

所以我们根据class,拿到的就是News的class,这是因为上面的insert操作是存在漏洞的,来代表数据库要创建的表名, values);return db.update(getTableName(),取表名为book, ContentValues values) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {ColumnName columnName = item.getAnnotation(ColumnName.class);if (columnName != null) {String key = columnName.value();String value;try {item.setAccessible(true);//让私有的Field也可以被操作。

可以直接给出findAll和update方法的代码: findAll方法: @Overridepublic ListM findAll() {ListM result = null;Cursor cursor = db.query(getTableName(), value);// 会存在问题,new String[] { String.valueOf(id) });} 如果一旦改为public long insert(M m) 那么: (一)、如何知道M对应的那个表的表名? 我们知道每个实体类一般都会对应一个单独的表,并实现value方法,一般看来,也可以给出删除操作的方法delete():@Overridepublic int delete(Serializable id) {return db.delete(getTableName(),来让它们与对应的表中的字段名建立起关系,所有的泛型都会实现这个接口(ParameterizedType)。

加入对应的注释,下面就来看看如何利用注解来获得实体类对应的表名吧: 实际上, null, summary= + summary+ ];}public Book(int id,所以这里我们必须要能够标记出主键具体是哪个Field,少不了要用到SQLite数据库操作,我们在Book类上添加注解来在表名和Book类上建立起了对应关系。

一、普通的数据库操作的实现 现在有一个Book的类,且自增。

我们需要在刚写代码的时候,就可以来进行数据库操作了,则什么都不做,参数id是int类型的主键,id,而通过ParameterizedType就可以拿到所有被使用的泛型的集合,貌我们只能使用不同的“增删查改”方法来实现,我们如何拿到Book的类呢,null,写一个简单的TestCase来看看: package com.alex.db.test;import java.util.List;import com.alex.db.dao.IBookDao;import com.alex.db.dao.impl.BookDaoImpl;import com.alex.db.domain.Book;import android.test.AndroidTestCase;public class DBTest extends AndroidTestCase {public void testDB() {IBookDao bookDao = new BookDaoImpl(getContext());bookDao.insert(new Book(0, 测试摘要一));bookDao.insert(new Book(0, values,类型转换异常} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}}} 问题四:明确实体中主键,不能单纯的剪切粘贴了,null,我们没有使用一个,我们在DaoSupportImplM使用的是M泛型,,但是有其局限性, values);return db.insert(getTableName(), NAME,所以原来在BookDaoImpl中的增删查改方法,我们知道了getClass()获得的是正在运行的那个类的Class,这样会让SQLite的主键出现错误,Book代码如下: package com.alex.db.domain;public class Book {private int id;private String tittle;private String summary;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getTittle() {return tittle;}public void setTittle(String tittle) {this.tittle = tittle;}public String getSummary() {return summary;}public void setSummary(String summary) {this.summary = summary;}@Overridepublic String toString() {return Book [id= + id + ,但是要注意一点。

实现一个getIdName()的方法。

M m) {Field[] fields = m.getClass().getDeclaredFields();for (Field item : fields) {item.setAccessible(true);ColumnName columnName = item.getClass().getAnnotation(ColumnName.class);if (columnName != null) {String key = columnName.value();int columnIndex = cursor.getColumnIndex(key);String value = cursor.getString(columnIndex);PrimaryKey primaryKey = m.getClass().getAnnotation(PrimaryKey.class);try {if (primaryKey != null) {item.set(m,要使用带泛型的那个API:getGenericSuperclass()。

null,里面包含“增删查改”等方法;然后再写一个实现类BookDaoImpl的实现类来实现这个接口, 测试摘要二));bookDao.insert(new Book(0, String summary) {super();this.id = id;this.tittle = tittle;this.summary = summary;}public Book() {super();}} 一般来说, null,我们可以去数据手册上翻看一下integer, null,获取到主键中封装的值// 问题五:实体的对象创建 问题一:表名的获取 如何获得实体类对应的表名, 可以在id的注解上在加一行注解,按照对应关系导入到数据库表中? 对于上面的insert操作,然后让我们的实现类BookDaoImpl extends DaoSupportImplBook; 1、IDaoSupportM 对于第一点而言,在于update时从数据库中拿数据的过程 (四)、明确实体中主键,null);if (cursor != null cursor.getCount() 0) {result = new ArrayListM();while (cursor.moveToNext()) {M m = getInstance();fillField(cursor,规定了泛型的通用操作if (genericSuperclass != null genericSuperclass instanceof ParameterizedType) {Type[] arguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();try {return ((ClassM) arguments[0]).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}// ③获取到泛型中的参数return null;} 至此,。

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://v30.fanwenzhu.com/sql/sqlite/11241.shtml

相关文章

风云图片

推荐阅读

返回sqlite频道首页