You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xiangmuyi/SqlData.java

236 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.gtask.data;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException;
import org.json.JSONObject;
// SqlData类主要用于处理与数据库中相关数据的交互操作能够从数据库游标加载数据、设置和获取JSON格式的数据内容以及将数据的变更提交到数据库等
public class SqlData {
// 用于日志记录的标签方便在Log输出中识别该类相关的日志信息使用类的简单名称作为标签
private static final String TAG = SqlData.class.getSimpleName();
// 定义一个表示无效ID的值通常用于初始化或者标识某个尚未正确赋值的ID情况
private static final int INVALID_ID = -99999;
// 定义查询数据时的投影(即要获取的列)数组,指定了从数据库获取数据时包含的列名
public static final String[] PROJECTION_DATA = new String[] {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3
};
// 定义在投影数组中数据ID列对应的索引位置方便后续从游标中获取对应列的值
public static final int DATA_ID_COLUMN = 0;
// 定义在投影数组中数据MIME_TYPE列对应的索引位置
public static final int DATA_MIME_TYPE_COLUMN = 1;
// 定义在投影数组中数据CONTENT列对应的索引位置
public static final int DATA_CONTENT_COLUMN = 2;
// 定义在投影数组中数据DATA1列对应的索引位置
public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
// 定义在投影数组中数据DATA3列对应的索引位置
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
// 用于与内容提供器进行交互,用于执行如插入、更新等数据操作
private ContentResolver mContentResolver;
// 标记当前对象所代表的数据是否是新创建的初始化为true表示新创建状态
private boolean mIsCreate;
// 存储数据的ID初始化为无效ID值
private long mDataId;
// 存储数据的MIME类型初始化为默认的NOTE类型可能来自DataConstants类
private String mDataMimeType;
// 存储数据的具体内容,初始化为空字符串
private String mDataContent;
// 存储数据内容中相关的一个长整型数据具体含义可能根据业务而定初始化为0
private long mDataContentData1;
// 存储数据内容中相关的一个字符串数据(具体含义可能根据业务而定),初始化为空字符串
private String mDataContentData3;
// 用于存储数据发生变更的内容值,方便后续批量提交变更到数据库
private ContentValues mDiffDataValues;
// 构造函数用于创建一个新的SqlData实例通常用于创建新的数据对象情况传入上下文用于获取内容解析器
public SqlData(Context context) {
// 获取上下文对应的内容解析器,用于后续与内容提供器交互操作
mContentResolver = context.getContentResolver();
// 标记为新创建状态
mIsCreate = true;
// 设置初始的无效数据ID
mDataId = INVALID_ID;
// 设置默认的MIME类型
mDataMimeType = DataConstants.NOTE;
// 设置初始的空内容字符串
mDataContent = "";
// 设置初始的相关数据值为0
mDataContentData1 = 0;
// 设置初始的相关数据字符串为空
mDataContentData3 = "";
// 初始化用于存储变更数据值的ContentValues对象
mDiffDataValues = new ContentValues();
}
// 另一个构造函数用于根据已有的数据库游标创建SqlData实例通常用于从数据库读取现有数据并封装到该对象中传入上下文和游标
public SqlData(Context context, Cursor c) {
// 获取上下文对应的内容解析器
mContentResolver = context.getContentResolver();
// 标记为非新创建状态,因为是从现有数据构建
mIsCreate = false;
// 从游标中加载数据到该对象的各个属性中
loadFromCursor(c);
// 初始化用于存储变更数据值的ContentValues对象
mDiffDataValues = new ContentValues();
}
// 从给定的游标中读取数据并设置到当前对象的对应属性中,根据之前定义的列索引位置获取相应的值
private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
mDataContent = c.getString(DATA_CONTENT_COLUMN);
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
// 根据传入的JSON对象设置当前对象的数据内容比较并更新有变化的数据项到mDiffDataValues中用于后续提交变更
public void setContent(JSONObject js) throws JSONException {
long dataId = js.has(DataColumns.ID)? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId!= dataId) {
mDiffDataValues.put(DataColumns.ID, dataId);
}
mDataId = dataId;
String dataMimeType = js.has(DataColumns.MIME_TYPE)? js.getString(DataColumns.MIME_TYPE)
: DataConstants.NOTE;
if (mIsCreate ||!mDataMimeType.equals(dataMimeType)) {
mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
}
mDataMimeType = dataMimeType;
String dataContent = js.has(DataColumns.CONTENT)? js.getString(DataColumns.CONTENT) : "";
if (mIsCreate ||!mDataContent.equals(dataContent)) {
mDiffDataValues.put(DataColumns.CONTENT, dataContent);
}
mDataContent = dataContent;
long dataContentData1 = js.has(DataColumns.DATA1)? js.getLong(DataColumns.DATA1) : 0;
if (mIsCreate || mDataContentData1!= dataContentData1) {
mDiffDataValues.put(DataColumns.DATA1, dataContentData1);
}
mDataContentData1 = dataContentData1;
String dataContentData3 = js.has(DataColumns.DATA3)? js.getString(DataColumns.DATA3) : "";
if (mIsCreate ||!mDataContentData3.equals(dataContentData3)) {
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
}
mDataContentData3 = dataContentData3;
}
// 将当前对象的数据内容转换为JSON对象返回如果是新创建状态尚未在数据库中存在则记录错误日志并返回null
public JSONObject getContent() throws JSONException {
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
JSONObject js = new JSONObject();
js.put(DataColumns.ID, mDataId);
js.put(DataColumns.MIME_TYPE, mDataMimeType);
js.put(DataColumns.CONTENT, mDataContent);
js.put(DataColumns.DATA1, mDataContentData1);
js.put(DataColumns.DATA3, mDataContentData3);
return js;
}
// 将数据的变更提交到数据库中,根据是新创建还是已有数据执行不同的操作(插入或更新),同时处理版本验证等逻辑
public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) {
// 如果是新创建数据且当前设置的ID为无效ID同时变更数据值中包含了ID字段则移除该ID字段可能是由数据库自动生成等情况
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID);
}
// 设置关联的笔记ID到变更数据值中以便插入时建立关联
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
// 通过内容解析器向指定的数据库URI插入数据获取插入后数据对应的URI
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
try {
// 尝试从插入后的URI中获取插入数据的ID设置到当前对象的mDataId属性中
mDataId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
// 如果获取ID过程出现格式转换异常记录错误日志并抛出操作失败异常表示创建笔记失败
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
} else {
// 如果是已有数据且有变更数据值(即有数据需要更新)
if (mDiffDataValues.size() > 0) {
int result = 0;
// 如果不需要验证版本
if (!validateVersion) {
// 直接执行更新操作更新对应数据ID的数据不做版本相关验证
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else {
// 如果需要验证版本则执行带版本验证条件的更新操作根据指定的笔记ID和版本号进行更新
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
"? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.VERSION + "=?)", new String[] {
String.valueOf(noteId), String.valueOf(version)
});
}
if (result == 0) {
// 如果更新操作没有实际更新任何数据,记录警告日志,可能是用户在同步时已经更新了笔记等情况
Log.w(TAG, "there is no update. maybe user updates note when syncing");
}
}
}
// 清除变更数据值,准备下一次的数据变更操作
mDiffDataValues.clear();
// 将创建标记设置为false表示当前数据已不是新创建状态
mIsCreate = false;
}
// 获取当前数据对象的ID值
public long getId() {
return mDataId;
}
}