多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 打造android ORM框架opendroid(二)――自動創建數據庫

打造android ORM框架opendroid(二)――自動創建數據庫

來源:程序員人生   發布時間:2015-02-06 08:52:36 閱讀次數:3232次

在上1篇博客《打造android ORM框架opendroid(1)――ORM框架的使用》中相信你已了解了opendroid的使用,那末從這篇博客開始,我們正式進入opendroid的源碼分析,打造1款自己的ORM框架!

在正式開始之前,你需要保證手里有1份opendroid的源碼,如果還沒下載opendroid,請到http://git.oschina.net/qibin/OpenDroid 下載opendroid的源碼。


任何數據庫操作都是從創建數據庫開始的,今天我們就來看看opendroid是怎樣幫我們自動創建數據庫的。 還記得關系映照怎樣配置嗎? 在open-droid.xml中,通過配置mapping節點來告知opendroid我們需要映照的java bean。那末數據庫操作是從什么時候開始的呢, 拿insert來講,就是調用了從OpenDroid繼承而來的save()方法!在這之前,我們沒有任何數據庫方面的操作,那末我們就從save()方法開始,看看opendroid是怎樣創建數據庫的。

/** * 插入數據 * @return 最后插入的id */ public long save() { try { Class<OpenDroid> klass = (Class<OpenDroid>) getClass(); ContentValues cv = new ContentValues(); generateData(klass, cv); return CRUD.insert(klass.getSimpleName(), cv, sSqliteDatabase); } catch (Exception e) { e.printStackTrace(); } return ⑴; }

第11行,通過調用了CRUD的1個靜態方法insert將數據保存到數據庫中,insert的最后1個參數sSqliteDatabas是我們關心的,來看看它的定義:

private static SQLiteDatabase sSqliteDatabase = sOpenHelper.getWritableDatabase();

sSqliteDatabase是通過sOpenHelper調用getWriteableDatabase()返回的,相信這里大家應當非常熟習了,再來看看sOpenHelper的定義:

private static CreateDB sOpenHelper = new CreateDB();

在這里直接new了1個CreateDB,通過類名我們完全可以知道CreateDB就是創建數據庫的關鍵。來看看CreateDB吧:

public class CreateDB extends SQLiteOpenHelper { public CreateDB() { super(DroidApplication.sContext, OpenDroidHelper.getDBInfoBean().getName(), null, OpenDroidHelper.getDBInfoBean().getVersion(), new DefaultDatabaseErrorHandler()); } @Override public void onCreate(SQLiteDatabase db) { for(String sql : OpenDroidHelper.getDBInfoBean().getSqls()) { db.execSQL(sql); } } }

這里我只截取了和創建數據庫有關的代碼, 可以看到CreateDB繼承自SQLiteOpenHelper,這里大家肯定也很熟習,先從構造方法開始看, 在構造方法中直接調用了父類的構造方法,第1個參數是1個context對象,這個對象是在DroidApplication中,其實很簡單,就是在onCreate中調用getApplicationContext()為DroidApplication中的sContext靜態變量賦值,這里就不貼代碼了,可以在源碼中找到,在看看接下來幾個參數,都是通過OpenDroidHelper.getDBInfoBean獲得的。再往后看看發現onCreate中也是通過遍歷OpenDroidHelper.getDBInfoBean().getSqls()來獲得創建表的sql語句,那末現在我們就去OpenDroidHelper看看吧。

public class OpenDroidHelper { public static final String TAG_DROID = "open-droid"; public static final String TAG_VERSION = "version"; public static final String TAG_NAME = "name"; public static final String TAG_MAPPING = "mapping"; private static DBBean sDBBean; public static DBBean getDBInfoBean() { if(sDBBean == null) { generateDBInfoBean(); } return sDBBean; } /** * 解析Asserts目錄下的open_droid.xml文件,生成DBInfoBean */ private static void generateDBInfoBean() { try { XmlPullParser pullParser = Xml.newPullParser(); InputStream inputStream = DroidApplication.sContext.getAssets().open("open_droid.xml"); pullParser.setInput(inputStream, "utf⑻"); int type = pullParser.getEventType(); String tagName = null; while(type != XmlPullParser.END_DOCUMENT) { if(type == XmlPullParser.START_TAG) { tagName = pullParser.getName(); if(tagName.equals(TAG_DROID)) { sDBBean = new DBBean(); }else if(tagName.equals(TAG_VERSION)) { // 獲得版本號 sDBBean.setVersion(Integer.parseInt(pullParser.getAttributeValue(null, "value"))); }else if(tagName.equals(TAG_NAME)) { // 獲得數據庫名 sDBBean.setName(pullParser.getAttributeValue(null, "value")); }else if(tagName.equals(TAG_MAPPING)) { // 獲得所有建表語句 sDBBean.addSql(generateSql(pullParser)); } } type = pullParser.next(); } } catch (Exception e) { e.printStackTrace(); } } /** * 生成建表sql語句 * @param pullParser * @return * @throws ClassNotFoundException * @throws XmlPullParserException * @throws IOException */ private static String generateSql(XmlPullParser pullParser) throws ClassNotFoundException, XmlPullParserException, IOException { // 反射獲得class Class<OpenDroid> klass = (Class<OpenDroid>) Class.forName(pullParser.getAttributeValue(null, "class")); StringBuilder sql = new StringBuilder("create table "); // 獲得類名, getSimpleName獲得類名, getName()獲得包名+類名 sql.append(klass.getSimpleName()).append("("); // 自動創建1個_id sql.append("_id integer primary key autoincrement,"); // 獲得所有的字段 Field[] fields = klass.getDeclaredFields(); for(Field field : fields) { // 如果是public的, 則表示不是1個表的字段 if(field.isAccessible()) { continue; } // 獲得字段名 String name = field.getName(); sql.append(name).append(" "); // 獲得字段類型 Class<?> fieldType = field.getType(); if(fieldType == String.class) { // 如果是String sql.append("text,"); }else if(fieldType == Integer.class || fieldType == int.class) { sql.append("integer,"); }else if(fieldType == Long.class || fieldType == long.class){ sql.append("integer,"); }else if(fieldType == Boolean.class || fieldType == boolean.class) { sql.append("boolean,"); }else if(fieldType == Float.class || fieldType == float.class) { sql.append("float,"); } } sql.replace(sql.length() - 1, sql.length(), ""); sql.append(");"); return sql.toString(); } }

額,代碼有點小長, 我們漸漸來看。首先來看看我們之前調用的getDBInfoBean(),這個方法很簡單,就是返回了1個DBBean對象,不過,它還調用了generateDBInfoBean()方法,通過方法名可以看出,它的作用是生成DBBean的。

/** * 解析Asserts目錄下的open_droid.xml文件,生成DBInfoBean */ private static void generateDBInfoBean() { try { XmlPullParser pullParser = Xml.newPullParser(); InputStream inputStream = DroidApplication.sContext.getAssets().open("open_droid.xml"); pullParser.setInput(inputStream, "utf⑻"); int type = pullParser.getEventType(); String tagName = null; while(type != XmlPullParser.END_DOCUMENT) { if(type == XmlPullParser.START_TAG) { tagName = pullParser.getName(); if(tagName.equals(TAG_DROID)) { sDBBean = new DBBean(); }else if(tagName.equals(TAG_VERSION)) { // 獲得版本號 sDBBean.setVersion(Integer.parseInt(pullParser.getAttributeValue(null, "value"))); }else if(tagName.equals(TAG_NAME)) { // 獲得數據庫名 sDBBean.setName(pullParser.getAttributeValue(null, "value")); }else if(tagName.equals(TAG_MAPPING)) { // 獲得所有建表語句 sDBBean.addSql(generateSql(pullParser)); } } type = pullParser.next(); } } catch (Exception e) { e.printStackTrace(); } }

恩,在generateDBInfoBean這個方法中,都是我們熟習的XMLPullParser的代碼,作用就是去解析open-droid.xml文件,獲得數據庫名稱、數據庫版本和數據表的信息。雖然很長,但是都很簡單,20行,我們獲得了數據庫的版本號,并保存到了DBBean中,一樣的23行獲得了數據庫的名稱,注意第26行,我們想DBBean中添加的sql語句,那添加的甚么sql語句呢? 肯定是建表的sql語句了。來看看generateSql()方法。


/** * 生成建表sql語句 * @param pullParser * @return * @throws ClassNotFoundException * @throws XmlPullParserException * @throws IOException */ private static String generateSql(XmlPullParser pullParser) throws ClassNotFoundException, XmlPullParserException, IOException { // 反射獲得class Class<OpenDroid> klass = (Class<OpenDroid>) Class.forName(pullParser.getAttributeValue(null, "class")); StringBuilder sql = new StringBuilder("create table "); // 獲得類名, getSimpleName獲得類名, getName()獲得包名+類名 sql.append(klass.getSimpleName()).append("("); // 自動創建1個_id sql.append("_id integer primary key autoincrement,"); // 獲得所有的字段 Field[] fields = klass.getDeclaredFields(); for(Field field : fields) { // 如果是public的, 則表示不是1個表的字段 if(field.isAccessible()) { continue; } // 獲得字段名 String name = field.getName(); sql.append(name).append(" "); // 獲得字段類型 Class<?> fieldType = field.getType(); if(fieldType == String.class) { // 如果是String sql.append("text,"); }else if(fieldType == Integer.class || fieldType == int.class) { sql.append("integer,"); }else if(fieldType == Long.class || fieldType == long.class){ sql.append("integer,"); }else if(fieldType == Boolean.class || fieldType == boolean.class) { sql.append("boolean,"); }else if(fieldType == Float.class || fieldType == float.class) { sql.append("float,"); } } sql.replace(sql.length() - 1, sql.length(), ""); sql.append(");"); return sql.toString(); }

generateSql()里面全是反射的代碼,如果你對反射還不熟習,建議你先去看看java反射,由于opendroid中大量使用了反射機制,

12行,通過反射獲得我們要映照的class,然后14~18行,是初始化創建表的sql語句,并且可以看到opendroid會自動為我們添加1個_id字段,所以在定義bean的時候,我們不需要再次定義了。

21行,獲得了這個類中定義的所有字段,并在22行循環遍歷這些字段。

14~26行,可以看到,如果字段是public的,那就疏忽它,所以如果你不想把某個字段映照到數據庫中,就定義成public的。

29~30行,是向創建表的sql語句中追加表名。

33~44行,通過判斷這個字段類型,來向創建表的sql語句中追加該字段的類型。

46行的作用是刪除最后1個的“,”

47行,就完成了該表的創建sql語句。


至此,opendroid的自動創建數據庫的流程我們就分析完了,現在來總結1下:

1、數據庫的創建我們借助了android API的SQLiteOpenHelper。

2、在SQLiteOpenHelper的onCreate中遍歷我們自動生成的建表語句并履行。

3、如何生成建表語句? 在OpenDroidHelper中通過反射獲得類的類名和字段名,并通過StringBuilder來拼湊建表語句。

4、為了方便,我們在OpenDroidHelper中將解析出來的數據名、數據庫版本和建表語句都放到了DBBean中,那末我們在CreateDB類中就能夠通過DBBean方便的獲得數據庫的信息了。


ok,數據庫的自動創建大體流程就是這樣,在接下來的博客中,我們還會去逐一介紹opendroid的CRUD操作和它的數據庫升級機制。


opendroid的開源地址:http://git.oschina.net/qibin/OpenDroid

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 一级一毛片 | 一二三四视频中文字幕在线看 | 精品一区二区三区五区六区 | 福利国产精品 | 高清欧美一区二区免费影视 | 国产一区二区三区免费播放 | 一本色道久久爱88a 一本视频在线 | 亚洲欧洲国产综合 | 日本夜免费视频视频大片 | 交在线观看网站视频 | 337p欧洲亚洲大胆艺术 | 黄色网址免费观看 | 日本一道本中文字幕 | 国内精品亚洲 | 最新激情网站 | 2020国产精品自拍 | 婷五月综合| 欧美一区亚洲二区 | 国产青草亚洲香蕉精品久久 | 色老头久久久久久久久久 | 国产精品视频一区二区三区不卡 | aa黄色片| 爰上碰23在线视频 | 久99久爱精品免费观看视频 | 国产精品久久成人影院 | 亚洲成人福利在线观看 | 午夜影院免费看 | 国产第一区二区三区在线观看 | 亚洲成熟 | 亚洲爽| 色综合久久综合欧美综合图片 | 久久a毛片 | 伊人8| 欧美一级看片免费观看视频在线 | 伊人性| 国产女人体一区二区三区 | 日韩欧美国产成人 | 日本特黄的免费大片视频 | 国产亚洲精品热视频在线观看 | 另类图片综合 | 色福利在线 |