LitePal數據庫框架 -- 源碼解析之創建數據庫

使用LitePal創建數據庫,表

準備工作:
①:引入LitePal jar包或者源碼
②:寫好實體類
public class News {
private int id;
private String title;
private String content;
private Date publishDate;
private int commentCount;
...get set 方法
}
③:在assets目錄下創建LitePal.xml文件,文件格式如下:
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<!-- 設置數據庫名字 -->
<dbname value="demo"></dbname>
<!-- 數據庫版本號 -->
<version value="1"></version>
<!-- 設置數據庫存儲位置 value=internal,external -->
<storage value="external"></storage>
<!-- 顯示數據庫查詢語句的大小寫,可以設置爲upper,lower,keep -->
<cases value="lower"></cases>
<!-- 設置所有表的映射模型 -->
<list>
<mapping class="com.example.databasetest.model.News"></mapping>
</list>
</litepal>
④:初始化Context對象
LitePal.initialize(getApplicationContext());
// getApplicationContext():獲取的是全局的Application對象
⑤:創建數據庫,表:Connector.getDatabase()

LitePal創建數據庫源碼解析

Connector.getDatabase()創建數據庫,表源碼解析
public static SQLiteDatabase getDatabase() {
return getWritableDatabase();
}
public synchronized static SQLiteDatabase getWritableDatabase() {
LitePalOpenHelper litePalHelper = buildConnection();
// 創建或更新數據庫
return litePalHelper.getWritableDatabase();
}
private static LitePalOpenHelper buildConnection() {
// 獲取LitePalAttr的屬性
LitePalAttr litePalAttr = LitePalAttr.getInstance();
// 檢查設置的屬性是否合法
litePalAttr.checkSelfValid();
if (mLitePalHelper == null) {
String dbName = litePalAttr.getDbName();
// 是否是外部存儲
if ("external".equalsIgnoreCase(litePalAttr.getStorage())) {
dbName = LitePalApplication.getContext().getExternalFilesDir("") + "/databases/" + dbName;
}
// 創建SQLiteOpenHelper類
mLitePalHelper = new LitePalOpenHelper(dbName, litePalAttr.getVersion());
}
return mLitePalHelper;
}

解析assets目錄下的LitePal.xml文件,並讀取裏面設置的值

獲取LitePalAttr類
public static LitePalAttr getInstance() {
if (litePalAttr == null) {
synchronized (LitePalAttr.class) {
if (litePalAttr == null) {
litePalAttr = new LitePalAttr();
// 判斷Assets目錄下是否存在LitePal.xml文件
if (BaseUtility.isLitePalXMLExists()) {
// 解析LitePal文件裏面的值並設置到LitePalAttr類中
LitePalConfig config = LitePalParser.parseLitePalConfiguration();
litePalAttr.setDbName(config.getDbName());
litePalAttr.setVersion(config.getVersion());
litePalAttr.setClassNames(config.getClassNames());
litePalAttr.setCases(config.getCases());
litePalAttr.setStorage(config.getStorage());
}
}
}
}
return litePalAttr;
}
判斷在assets目錄下面是否存在LitePal.xml文件
public static boolean isLitePalXMLExists() {
try {
AssetManager assetManager = LitePalApplication.getContext().getAssets();
String[] fileNames = assetManager.list("");
if (fileNames != null && fileNames.length > 0) {
for (String fileName : fileNames) {
if (Const.Config.CONFIGURATION_FILE_NAME.equalsIgnoreCase(fileName)) {
return true;
}
}
}
} catch (IOException e) {
}
return false;
}
解析LitePal.xml文件,並取出裏面的值,使用的是Pull解析
public static LitePalConfig parseLitePalConfiguration() {
if (parser == null) {
parser = new LitePalParser();
}
return parser.usePullParse();
}
private LitePalConfig usePullParse() {
try {
LitePalConfig litePalConfig = new LitePalConfig();
// 使用pull解析
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(getConfigInputStream(), "UTF-8");
int eventType = xmlPullParser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String nodeName = xmlPullParser.getName();
switch (eventType) {
case XmlPullParser.START_TAG: {
// 解析的標籤有:dbname,version,mapping,cases,storage;標籤的屬性有:value,class
// 從解析LitePal文件可以知道LitePal文件的規範
if (NODE_DB_NAME.equals(nodeName)) {
String dbName = xmlPullParser.getAttributeValue("", ATTR_VALUE);
litePalConfig.setDbName(dbName);
} else if (NODE_VERSION.equals(nodeName)) {
String version = xmlPullParser.getAttributeValue("", ATTR_VALUE);
litePalConfig.setVersion(Integer.parseInt(version));
} else if (NODE_MAPPING.equals(nodeName)) {
String className = xmlPullParser.getAttributeValue("", ATTR_CLASS);
litePalConfig.addClassName(className);
} else if (NODE_CASES.equals(nodeName)) {
String cases = xmlPullParser.getAttributeValue("", ATTR_VALUE);
litePalConfig.setCases(cases);
} else if (NODE_STORAGE.equals(nodeName)) {
String storage = xmlPullParser.getAttributeValue("", ATTR_VALUE);
litePalConfig.setStorage(storage);
}
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}
return litePalConfig;
} catch (XmlPullParserException e) {
throw new ParseConfigurationFileException(
ParseConfigurationFileException.FILE_FORMAT_IS_NOT_CORRECT);
} catch (IOException e) {
throw new ParseConfigurationFileException(ParseConfigurationFileException.IO_EXCEPTION);
}
}
檢查LitePal.xml配置文件裏面設置的屬性是否合法
public void checkSelfValid() {
// 數據庫名不能爲空
if (TextUtils.isEmpty(dbName)) {
throw new InvalidAttributesException(
InvalidAttributesException.DBNAME_IS_EMPTY_OR_NOT_DEFINED);
}
// 數據庫名是否有.db後綴,如果沒有加上.db後綴
if (!dbName.endsWith(Const.Config.DB_NAME_SUFFIX)) {
dbName = dbName + Const.Config.DB_NAME_SUFFIX;
}
// 數據庫版本號不能小於1
if (version < 1) {
throw new InvalidAttributesException(
InvalidAttributesException.VERSION_OF_DATABASE_LESS_THAN_ONE);
}
// 數據庫版本不能小於上一次的版本
if (version < SharedUtil.getLastVersion(extraKeyName)) {
throw new InvalidAttributesException(
InvalidAttributesException.VERSION_IS_EARLIER_THAN_CURRENT);
}
// 默認設置數據庫語句爲小寫
if (TextUtils.isEmpty(cases)) {
cases = Const.Config.CASES_LOWER;
} else {
if (!cases.equals(Const.Config.CASES_UPPER)
&& !cases.equals(Const.Config.CASES_LOWER)
&& !cases.equals(Const.Config.CASES_KEEP)) {
throw new InvalidAttributesException(cases
+ InvalidAttributesException.CASES_VALUE_IS_INVALID);
}
}
}
是否存儲到外部存儲設備
if (mLitePalHelper == null) {
String dbName = litePalAttr.getDbName();
if ("external".equalsIgnoreCase(litePalAttr.getStorage())) {
dbName = LitePalApplication.getContext().getExternalFilesDir("") + "/databases/" + dbName;
}
mLitePalHelper = new LitePalOpenHelper(dbName, litePalAttr.getVersion());
}

創建SQLiteOpenHelper類

mLitePalHelper = new LitePalOpenHelper(dbName, litePalAttr.getVersion());

執行創建數據庫操作

litePalHelper.getWritableDatabase();
如果是第一次創建,則會執行onCreate方法
@Override
public void onCreate(SQLiteDatabase db) {
Generator.create(db);
}
Generator類的create方法
static void create(SQLiteDatabase db) {
// 創建數據庫
create(db, true);
// 增加表之間的關聯
addAssociation(db, true);
}

把實體類轉換成對應的表model

private static void create(SQLiteDatabase db, boolean force) {
Creator creator = new Creator();
creator.createOrUpgradeTable(db, force);
}
@Override
protected void createOrUpgradeTable(SQLiteDatabase db, boolean force) {
for (TableModel tableModel : getAllTableModels()) {
// 創建或更新表
createOrUpgradeTable(tableModel, db, force);
}
}
protected Collection<TableModel> getAllTableModels() {
if (mTableModels == null) {
mTableModels = new ArrayList<TableModel>();
}
if (!canUseCache()) {
mTableModels.clear();
for (String className : LitePalAttr.getInstance().getClassNames()) {
mTableModels.add(getTableModel(className));
}
}
return mTableModels;
}
protected TableModel getTableModel(String className) {
// 獲取類名
String tableName = DBUtility.getTableNameByClassName(className);
// 創建每張表的model
TableModel tableModel = new TableModel();
tableModel.setTableName(tableName);
tableModel.setClassName(className);
// 獲取這個類的字段,並設置到對應的表model中
List<Field> supportedFields = getSupportedFields(className);
for (Field field : supportedFields) {
ColumnModel columnModel = convertFieldToColumnModel(field);
tableModel.addColumnModel(columnModel);
}
return tableModel;
}
protected List<Field> getSupportedFields(String className) {
List<Field> fieldList = classFieldsMap.get(className);
if (fieldList == null) {
List<Field> supportedFields = new ArrayList<Field>();
Class<?> clazz;
try {
// 通過反射獲取這個類的Class對象
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new DatabaseGenerateException(DatabaseGenerateException.CLASS_NOT_FOUND + className);
}
// 遞歸查詢類的字段,可以查詢父類的字段
recursiveSupportedFields(clazz, supportedFields);
// 把類的字段設置到map中,以classname爲key
classFieldsMap.put(className, supportedFields);
return supportedFields;
}
return fieldList;
}
private void recursiveSupportedFields(Class<?> clazz, List<Field> supportedFields) {
// 如果遞歸查詢到DataSupport類或者Object類,則退出,默認所有的類都繼承    Object類
if (clazz == DataSupport.class || clazz == Object.class) {
return;
}
// 獲取類的字段,包括公共,保護,默認(包)訪問和私有字段,但不包括繼承的字段
Field[] fields = clazz.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
// 獲取字段上面的註解
Column annotation = field.getAnnotation(Column.class);
// 如果有註解,並且註解的ignore爲true則不加入
if (annotation != null && annotation.ignore()) {
continue;
}
// 獲取字段的修飾符
int modifiers = field.getModifiers();
// 如果是靜態(static)字段則不加入
if (!Modifier.isStatic(modifiers)) {
Class<?> fieldTypeClass = field.getType();
String fieldType = fieldTypeClass.getName();
// 判斷是否支持此字段的類型,包括:boollean, float, double, int, long, short, char, byte, String, Date
if (BaseUtility.isFieldTypeSupported(fieldType)) {
supportedFields.add(field);
}
}
}
}
// 遞歸查詢,查詢父類的字段clazz.getSupper
recursiveSupportedFields(clazz.getSuperclass(), supportedFields);
}
支持的字段的類型
public static boolean isFieldTypeSupported(String fieldType) {
if ("boolean".equals(fieldType) || "java.lang.Boolean".equals(fieldType)) {
return true;
}
if ("float".equals(fieldType) || "java.lang.Float".equals(fieldType)) {
return true;
}
if ("double".equals(fieldType) || "java.lang.Double".equals(fieldType)) {
return true;
}
if ("int".equals(fieldType) || "java.lang.Integer".equals(fieldType)) {
return true;
}
if ("long".equals(fieldType) || "java.lang.Long".equals(fieldType)) {
return true;
}
if ("short".equals(fieldType) || "java.lang.Short".equals(fieldType)) {
return true;
}
if ("char".equals(fieldType) || "java.lang.Character".equals(fieldType)) {
return true;
}
if ("[B".equals(fieldType) || "[Ljava.lang.Byte;".equals(fieldType)) {
return true;
}
if ("java.lang.String".equals(fieldType) || "java.util.Date".equals(fieldType)) {
return true;
}
return false;
}
把一個字段轉變成ColumnModel
private ColumnModel convertFieldToColumnModel(Field field) {
// 子段的名稱
String fieldType = field.getType().getName();
// 獲取字段的類型
String columnType = getColumnType(fieldType);
boolean nullable = true;
boolean unique = false;
String defaultValue = "";
// 獲取字段上面的註解
Column annotation = field.getAnnotation(Column.class);
if (annotation != null) {
nullable = annotation.nullable();
unique = annotation.unique();
defaultValue = annotation.defaultValue();
}
ColumnModel columnModel = new ColumnModel();
// 判斷列名是否合法,因爲列名有可能會和sql語句關鍵字衝突
columnModel.setColumnName(DBUtility.convertToValidColumnName(field.getName()));
columnModel.setColumnType(columnType);
columnModel.setIsNullable(nullable);
columnModel.setIsUnique(unique);
columnModel.setDefaultValue(defaultValue);
return columnModel;
}
protected String getColumnType(String fieldType) {
String columnType;
for (OrmChange ormChange : typeChangeRules) {
// 返回字段的類型
columnType = ormChange.object2Relation(fieldType);
if (columnType != null) {
return columnType;
}
}
return null;
}
當前數組中的所有支持映射類型
private OrmChange[] typeChangeRules = { new NumericOrm(), new TextOrm(), new BooleanOrm(),
new DecimalOrm(), new DateOrm(), new BlobOrm()};
列名關鍵字合法性判斷
public static String convertToValidColumnName(String columnName) {
if (isFieldNameConflictWithSQLiteKeywords(columnName)) {
// 如果有衝突則在列名後面_lpcolumn
return columnName + KEYWORDS_COLUMN_SUFFIX;
}
return columnName;
}
public static boolean isFieldNameConflictWithSQLiteKeywords(String fieldName) {
if (!TextUtils.isEmpty(fieldName)) {
String fieldNameWithComma = "," + fieldName.toLowerCase() + ",";
if (SQLITE_KEYWORDS.contains(fieldNameWithComma)) {
return true;
}
}
return false;
}
關鍵字如下:
,abort,add,after,all,alter,and,as,asc,autoincrement,before,begin,between,by,cascade,check,collate,column,commit,conflict,constraint,create,cross,database,deferrable,deferred,delete,desc,distinct,drop,each,end,escape,except,exclusive,exists,foreign,from,glob,group,having,in,index,inner,insert,intersect,into,is,isnull,join,like,limit,match,natural,not,notnull,null,of,offset,on,or,order,outer,plan,pragma,primary,query,raise,references,regexp,reindex,release,rename,replace,restrict,right,rollback,row,savepoint,select,set,table,temp,temporary,then,to,transaction,trigger,union,unique,update,using,vacuum,values,view,virtual,when,where,

執行Sql語句創建表

@Override
protected void createOrUpgradeTable(SQLiteDatabase db, boolean force) {
for (TableModel tableModel : getAllTableModels()) {
createOrUpgradeTable(tableModel, db, force);
}
}
 
protected void createOrUpgradeTable(TableModel tableModel, SQLiteDatabase db, boolean force) {
execute(getCreateTableSQLs(tableModel, db, force), db);
giveTableSchemaACopy(tableModel.getTableName(), Const.TableSchema.NORMAL_TABLE, db);
}
獲取Sql語句
protected String[] getCreateTableSQLs(TableModel tableModel, SQLiteDatabase db, boolean force) {
// force:true,則創建表之前判斷是否存在表,存在就先刪除,再創建;false:直接創建
if (force) {
return new String[] { generateDropTableSQL(tableModel),
generateCreateTableSQL(tableModel) };
} else {
if (DBUtility.isTableExists(tableModel.getTableName(), db)) {
return null;
} else {
return new String[] { generateCreateTableSQL(tableModel) };
}
}
}
刪除表的sql語句
protected String generateDropTableSQL(String tableName) {
return "drop table if exists " + tableName;
}
創建表的sql語句
protected String generateCreateTableSQL(String tableName, List<ColumnModel> columnModels,
boolean autoIncrementId) {
StringBuilder createTableSQL = new StringBuilder("create table ");
createTableSQL.append(tableName).append(" (");
if (autoIncrementId) {
createTableSQL.append("id integer primary key autoincrement,");
}
if (columnModels.size() == 0) {
createTableSQL.deleteCharAt(createTableSQL.length() - 1);
}
boolean needSeparator = false;
for (ColumnModel columnModel : columnModels) {
if (columnModel.isIdColumn()) {
continue;
}
if (needSeparator) {
createTableSQL.append(", ");
}
needSeparator = true;
createTableSQL.append(columnModel.getColumnName()).append(" ").append(columnModel.getColumnType());
if (!columnModel.isNullable()) {
createTableSQL.append(" not null");
}
if (columnModel.isUnique()) {
createTableSQL.append(" unique");
}
String defaultValue = columnModel.getDefaultValue();
if (!TextUtils.isEmpty(defaultValue)) {
createTableSQL.append(" default ").append(defaultValue);
}
}
createTableSQL.append(")");
LogUtil.d(TAG, "create table sql is >> " + createTableSQL);
return createTableSQL.toString();
}
執行sql語句
protected void execute(String[] sqls, SQLiteDatabase db) {
String throwSQL = "";
try {
if (sqls != null) {
for (String sql : sqls) {
throwSQL = sql;
// 執行sql語句,並設置sql語句的顯示方式,主要有三種顯示方式:keep, upper, lower
db.execSQL(BaseUtility.changeCase(sql));
}
}
} catch (SQLException e) {
throw new DatabaseGenerateException(DatabaseGenerateException.SQL_ERROR + throwSQL);
}
}
public static String changeCase(String string) {
if (string != null) {
LitePalAttr litePalAttr = LitePalAttr.getInstance();
String cases = litePalAttr.getCases();
if (Const.Config.CASES_KEEP.equals(cases)) {
return string;
} else if (Const.Config.CASES_UPPER.equals(cases)) {
return string.toUpperCase(Locale.US);
}
return string.toLowerCase(Locale.US);
}
return null;
}

新表創建時,把表名保存到table_schema表中,每張表只保存一次

protected void giveTableSchemaACopy(String tableName, int tableType, SQLiteDatabase db) {
// tableType:0代表正常的表,1代表中間連接表
StringBuilder sql = new StringBuilder("select * from ");
sql.append(Const.TableSchema.TABLE_NAME);
LogUtil.d(TAG, "giveTableSchemaACopy SQL is >> " + sql);
Cursor cursor = null;
try {
cursor = db.rawQuery(sql.toString(), null);
// 是否需要把新表保存到schema表中
if (isNeedtoGiveACopy(cursor, tableName)) {
ContentValues values = new ContentValues();
values.put(Const.TableSchema.COLUMN_NAME, BaseUtility.changeCase(tableName));
values.put(Const.TableSchema.COLUMN_TYPE, tableType);
db.insert(Const.TableSchema.TABLE_NAME, null, values);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
}

創建關聯表

private static void addAssociation(SQLiteDatabase db, boolean force) {
AssociationCreator associationsCreator = new Creator();
// 增加表之間的關聯
associationsCreator.addOrUpdateAssociation(db, force);
}
獲取所有的關聯
protected Collection<AssociationsModel> getAllAssociations() {
if (mAllRelationModels == null || mAllRelationModels.isEmpty()) {
mAllRelationModels = getAssociations(LitePalAttr.getInstance().getClassNames());
}
return mAllRelationModels;
}
protected Collection<AssociationsModel> getAssociations(List<String> classNames) {
if (mAssociationModels == null) {
mAssociationModels = new HashSet<AssociationsModel>();
}
if (mGenericModels == null) {
mGenericModels = new HashSet<GenericModel>();
}
mAssociationModels.clear();
mGenericModels.clear();
for (String className : classNames) {
analyzeClassFields(className, GET_ASSOCIATIONS_ACTION);
}
return mAssociationModels;
}
private void analyzeClassFields(String className, int action) {
// 分析字段來查詢表之間是否有關聯
try {
Class<?> dynamicClass = Class.forName(className);
Field[] fields = dynamicClass.getDeclaredFields();
for (Field field : fields) {
if (isPrivateAndNonPrimitive(field)) {
oneToAnyConditions(className, field, action);
manyToAnyConditions(className, field, action);
}
}
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
throw new DatabaseGenerateException(DatabaseGenerateException.CLASS_NOT_FOUND + className);
}
}
處理一對一,一對多的表關聯
private void oneToAnyConditions(String className, Field field, int action) throws ClassNotFoundException {
Class<?> fieldTypeClass = field.getType();
// If the mapping list contains the class name
// defined in one class.
if (LitePalAttr.getInstance().getClassNames().contains(fieldTypeClass.getName())) {
Class<?> reverseDynamicClass = Class.forName(fieldTypeClass.getName());
Field[] reverseFields = reverseDynamicClass.getDeclaredFields();
// Look up if there's a reverse association
// definition in the reverse class.
boolean reverseAssociations = false;
// Begin to check the fields of the defined
// class.
for (int i = 0; i < reverseFields.length; i++) {
Field reverseField = reverseFields[i];
if (!Modifier.isStatic(reverseField.getModifiers())) {
Class<?> reverseFieldTypeClass = reverseField.getType();
// If there's the from class name in the
// defined class, they are one2one bidirectional
// associations.
if (className.equals(reverseFieldTypeClass.getName())) {
if (action == GET_ASSOCIATIONS_ACTION) {
addIntoAssociationModelCollection(className, fieldTypeClass.getName(),
fieldTypeClass.getName(), Const.Model.ONE_TO_ONE);
} else if (action == GET_ASSOCIATION_INFO_ACTION) {
addIntoAssociationInfoCollection(className, fieldTypeClass.getName(),
fieldTypeClass.getName(), field, reverseField, Const.Model.ONE_TO_ONE);
}
reverseAssociations = true;
}
// If there's the from class Set or List in
// the defined class, they are many2one bidirectional
// associations.
else if (isCollection(reverseFieldTypeClass)) {
String genericTypeName = getGenericTypeName(reverseField);
if (className.equals(genericTypeName)) {
if (action == GET_ASSOCIATIONS_ACTION) {
addIntoAssociationModelCollection(className, fieldTypeClass.getName(),
className, Const.Model.MANY_TO_ONE);
} else if (action == GET_ASSOCIATION_INFO_ACTION) {
addIntoAssociationInfoCollection(className, fieldTypeClass.getName(),
className, field, reverseField, Const.Model.MANY_TO_ONE);
}
reverseAssociations = true;
}
}
}
}
// If there's no from class in the defined class, they are
// one2one unidirectional associations.
if (!reverseAssociations) {
if (action == GET_ASSOCIATIONS_ACTION) {
addIntoAssociationModelCollection(className, fieldTypeClass.getName(),
fieldTypeClass.getName(), Const.Model.ONE_TO_ONE);
} else if (action == GET_ASSOCIATION_INFO_ACTION) {
addIntoAssociationInfoCollection(className, fieldTypeClass.getName(),
fieldTypeClass.getName(), field, null, Const.Model.ONE_TO_ONE);
}
}
}
}
處理多對多的表關聯
private void manyToAnyConditions(String className, Field field, int action) throws ClassNotFoundException {
if (isCollection(field.getType())) {
String genericTypeName = getGenericTypeName(field);
// If the mapping list contains the genericTypeName, begin to check
// this genericTypeName class.
if (LitePalAttr.getInstance().getClassNames().contains(genericTypeName)) {
Class<?> reverseDynamicClass = Class.forName(genericTypeName);
Field[] reverseFields = reverseDynamicClass.getDeclaredFields();
// Look up if there's a reverse association
// definition in the reverse class.
boolean reverseAssociations = false;
for (int i = 0; i < reverseFields.length; i++) {
Field reverseField = reverseFields[i];
// Only map private fields
if (!Modifier.isStatic(reverseField.getModifiers())) {
Class<?> reverseFieldTypeClass = reverseField.getType();
// If there's a from class name defined in the reverse
// class, they are many2one bidirectional
// associations.
if (className.equals(reverseFieldTypeClass.getName())) {
if (action == GET_ASSOCIATIONS_ACTION) {
addIntoAssociationModelCollection(className, genericTypeName,
genericTypeName, Const.Model.MANY_TO_ONE);
} else if (action == GET_ASSOCIATION_INFO_ACTION) {
addIntoAssociationInfoCollection(className, genericTypeName, genericTypeName,
field, reverseField, Const.Model.MANY_TO_ONE);
}
reverseAssociations = true;
}
// If there's a List or Set contains from class name
// defined in the reverse class, they are many2many
// association.
else if (isCollection(reverseFieldTypeClass)) {
String reverseGenericTypeName = getGenericTypeName(reverseField);
if (className.equals(reverseGenericTypeName)) {
if (action == GET_ASSOCIATIONS_ACTION) {
addIntoAssociationModelCollection(className, genericTypeName, null,
Const.Model.MANY_TO_MANY);
} else if (action == GET_ASSOCIATION_INFO_ACTION) {
addIntoAssociationInfoCollection(className, genericTypeName, null, field,
reverseField, Const.Model.MANY_TO_MANY);
}
reverseAssociations = true;
}
}
 
}
}
// If there's no from class in the defined class, they
// are many2one unidirectional associations.
if (!reverseAssociations) {
if (action == GET_ASSOCIATIONS_ACTION) {
addIntoAssociationModelCollection(className, genericTypeName,
genericTypeName, Const.Model.MANY_TO_ONE);
} else if (action == GET_ASSOCIATION_INFO_ACTION) {
addIntoAssociationInfoCollection(className, genericTypeName, genericTypeName,
field, null, Const.Model.MANY_TO_ONE);
}
}
} else if(BaseUtility.isGenericTypeSupported(genericTypeName) && action == GET_ASSOCIATIONS_ACTION) {
Column annotation = field.getAnnotation(Column.class);
if (annotation != null && annotation.ignore()) {
return;
}
GenericModel genericModel = new GenericModel();
genericModel.setTableName(DBUtility.getGenericTableName(className, field.getName()));
genericModel.setValueColumnName(DBUtility.convertToValidColumnName(field.getName()));
genericModel.setValueColumnType(getColumnType(genericTypeName));
genericModel.setValueIdColumnName(DBUtility.getGenericValueIdColumnName(className));
mGenericModels.add(genericModel);
}
}
}
分析表關聯關係,如果是一對一,一對多的關聯,則在多的一方加入外鍵;如果是多對多的關聯則創建中間表
private void addAssociations(Collection<AssociationsModel> associatedModels, SQLiteDatabase db,
boolean force) {
for (AssociationsModel associationModel : associatedModels) {
if (Const.Model.MANY_TO_ONE == associationModel.getAssociationType()
|| Const.Model.ONE_TO_ONE == associationModel.getAssociationType()) {
addForeignKeyColumn(associationModel.getTableName(),
associationModel.getAssociatedTableName(),
associationModel.getTableHoldsForeignKey(), db);
} else if (Const.Model.MANY_TO_MANY == associationModel.getAssociationType()) {
createIntermediateTable(associationModel.getTableName(),
associationModel.getAssociatedTableName(), db, force);
}
}
for (GenericModel genericModel : getGenericModels()) {
createGenericTable(genericModel, db, force);
}
}

相關文章


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章