XUtils 源码分析(三)--数据库操作模块
来源:互联网 发布:whenyoubelieve知乎 编辑:程序博客网 时间:2024/06/05 08:20
一 数据库创建
1.客户端程序:
DbUtils.DaoConfig config = new DbUtils.DaoConfig(context);
config.setDbName("user.db");
mUserInforDbUtils = DbUtils.create(config);
2.DbUtils的创建函数:
public static DbUtils create(DaoConfig daoConfig) {
return getInstance(daoConfig);
}
3.私有静态方法获取DbUtils实例:先检查缓存,没有就去创建。
/**
* 获取一个DbUtils,首先检查Map是否有缓存,没有新建添加到Map中
*/
private synchronized static DbUtils getInstance(DaoConfig daoConfig) {
DbUtils dao = daoMap.get(daoConfig.getDbName());
if (dao == null) {
dao = new DbUtils(daoConfig);//生成数据库操作对象,新建数据库
daoMap.put(daoConfig.getDbName(), dao);//存放数据库操作对象
} else {
dao.daoConfig = daoConfig;//更新配置
}
//处理数据库更新问题
SQLiteDatabase database = dao.database;
int oldVersion = database.getVersion();
int newVersion = daoConfig.getDbVersion();
if (oldVersion != newVersion) {//版本不一致
if (oldVersion != 0) {
DbUpgradeListener upgradeListener = daoConfig.getDbUpgradeListener();
if (upgradeListener != null) {
upgradeListener.onUpgrade(dao, oldVersion, newVersion);//用户自定义更新
} else {//清空旧的数据库
try {
dao.dropDb();
} catch (DbException e) {
LogUtils.e(e.getMessage(), e);
}
}
}
database.setVersion(newVersion);
}
return dao;
}
3.1 私有构造方法:
private DbUtils(DaoConfig config) {
if (config == null) {
throw new IllegalArgumentException("daoConfig may not be null");
}
this.database = createDatabase(config);
this.daoConfig = config;
}
3.1.1 构造方法生成的数据库createDatabase(config):
/*
* 新建数据库
*/
private SQLiteDatabase createDatabase(DaoConfig config) {
SQLiteDatabase result = null;
String dbDir = config.getDbDir();
if (!TextUtils.isEmpty(dbDir)) {//数据库路径不为空
File dir = new File(dbDir);
if (dir.exists() || dir.mkdirs()) {
File dbFile = new File(dbDir, config.getDbName());
result = SQLiteDatabase.openOrCreateDatabase(dbFile, null);//生成数据库文件
}
} else {//生成数据库对象
result = config.getContext().openOrCreateDatabase(config.getDbName(), 0, null);
}
return result;
}
3.2清空数据库:
/**
* 清空数据库
*/
public void dropDb() throws DbException {
Cursor cursor = execQuery("SELECT name FROM sqlite_master WHERE type='table' AND name<>'sqlite_sequence'");
//获得数据库中的所有表
if (cursor != null) {
try {
while (cursor.moveToNext()) {
try {
String tableName = cursor.getString(0);
execNonQuery("DROP TABLE " + tableName);//清空
Table.remove(this, tableName);
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
} catch (Throwable e) {
throw new DbException(e);
} finally {
IOUtils.closeQuietly(cursor);
}
}
}
4.客户端存储数据:
try {
mUserInforDbUtils.save(user); // 使用saveBindingId保存实体时会为实体的id赋值
} catch (DbException e) {
e.printStackTrace();
}
4.1 save函数 mUserInforDbUtils.save(user);
/**
* 数据库存储记录
*/
public void save(Object entity) throws DbException {
try {
beginTransaction();//开启事务
createTableIfNotExist(entity.getClass());//检测表是否存在,不存在就新建
execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity));
setTransactionSuccessful();
} finally {
endTransaction();
}
}
/**
* 开启事务管理
*/
private void beginTransaction() {
if (allowTransaction) {//允许开启
database.beginTransaction();
} else {//不允许锁定
writeLock.lock();
writeLocked = true;
}
}
4.1.2 表不存在就创建 createTableIfNotExist(entity.getClass());
/**
* 不存在表就新建
*/
public void createTableIfNotExist(Class<?> entityType) throws DbException {
if (!tableIsExist(entityType)) {//表不存在,注意表对象已存在
SqlInfo sqlInfo = SqlInfoBuilder.buildCreateTableSqlInfo(this, entityType);//生成SQL语句对象
execNonQuery(sqlInfo);//执行语句,建表
String execAfterTableCreated = TableUtils.getExecAfterTableCreated(entityType);
if (!TextUtils.isEmpty(execAfterTableCreated)) {
execNonQuery(execAfterTableCreated);//设置表默认值
}
}
}
/**
* 判断表是否存在
*/
public boolean tableIsExist(Class<?> entityType) throws DbException {
Table table = Table.get(this, entityType);//根据类对象获取表
if (table.isCheckedDatabase()) {
return true;
}
Cursor cursor = execQuery("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='" + table.tableName + "'");//查找制定表
if (cursor != null) {
try {
if (cursor.moveToNext()) {
int count = cursor.getInt(0);
if (count > 0) {//存在指定的表
table.setCheckedDatabase(true);
return true;
}
}
} catch (Throwable e) {
throw new DbException(e);
} finally {
IOUtils.closeQuietly(cursor);
}
}
return false;
}
4.1.2.1.1 获取表对象Table.get(this, entityType);缓存中去找没有去新建
/**
* 获取表
*/
public static synchronized Table get(DbUtils db, Class<?> entityType) {
String tableKey = db.getDaoConfig().getDbName() + "#" + entityType.getName();
Table table = tableMap.get(tableKey);
if (table == null) {//没有缓存
table = new Table(db, entityType);
tableMap.put(tableKey, table);
}
return table;
}
4.1.2.1.1.1 Table私有构造方法:
private Table(DbUtils db, Class<?> entityType) {
this.db = db;
this.tableName = TableUtils.getTableName(entityType);//获取表名
this.id = TableUtils.getId(entityType);
this.columnMap = TableUtils.getColumnMap(entityType);//获取列MAP
finderMap = new HashMap<String, Finder>();
for (Column column : columnMap.values()) {//得到主表列对象
column.setTable(this);
if (column instanceof Finder) {
finderMap.put(column.getColumnName(), (Finder) column);
}
}
}
4.1.2.1.1.1.1 获取表名 TableUtils.getTableName(entityType);
public static String getTableName(Class<?> entityType) {
Table table = entityType.getAnnotation(Table.class);
if (table == null || TextUtils.isEmpty(table.name())) {//没有注解字段Table
return entityType.getName().replace('.', '_');
}
return table.name();
}
4.1.2.1.1.1.2 获取表的列对象 TableUtils.getColumnMap(entityType);
/**
* 根据类对象获取列对象的MAP
*/
static synchronized HashMap<String, Column> getColumnMap(Class<?> entityType) {
if (entityColumnsMap.containsKey(entityType.getName())) {//这个类已经存储过了数据库列对象
return entityColumnsMap.get(entityType.getName());
}
HashMap<String, Column> columnMap = new HashMap<String, Column>();
String primaryKeyFieldName = getPrimaryKeyFieldName(entityType);
addColumns2Map(entityType, primaryKeyFieldName, columnMap);//缓存类对象的属性指为Columns对象
entityColumnsMap.put(entityType.getName(), columnMap);//缓存这个数据表的Columns对象MAP集
return columnMap;
}
4.1.2.1.1.1.2.1 缓存列对象addColumns2Map(entityType, primaryKeyFieldName, columnMap);
/**
* 缓存类对象的属性指为Columns对象
*/
private static void addColumns2Map(Class<?> entityType, String primaryKeyFieldName, HashMap<String, Column> columnMap) {
if (Object.class.equals(entityType)) return;
try {
Field[] fields = entityType.getDeclaredFields();
for (Field field : fields) {
if (ColumnUtils.isTransient(field) || Modifier.isStatic(field.getModifiers())) {//忽略static及注解Transient的属性
continue;
}
if (ColumnConverterFactory.isSupportColumnConverter(field.getType())) {//属性字段支持列对象转换
if (!field.getName().equals(primaryKeyFieldName)) {//不是ID字段
Column column = new Column(entityType, field);
if (!columnMap.containsKey(column.getColumnName())) {//缓存列对象
columnMap.put(column.getColumnName(), column);
}
}
} else if (ColumnUtils.isForeign(field)) {// 属性字段是Foreign注解,从表注解
Foreign column = new Foreign(entityType, field);
if (!columnMap.containsKey(column.getColumnName())) {
columnMap.put(column.getColumnName(), column);
}
} else if (ColumnUtils.isFinder(field)) {//属性字段是Finder,主表注解
Finder column = new Finder(entityType, field);
if (!columnMap.containsKey(column.getColumnName())) {
columnMap.put(column.getColumnName(), column);
}
}
}
if (!Object.class.equals(entityType.getSuperclass())) {//继续将父类属性字段缓存
addColumns2Map(entityType.getSuperclass(), primaryKeyFieldName, columnMap);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
4.1.2.1.1.1.2.1.1 判断属性字段时候支持列对象转换
/**
* 检查是否支持Column对象转换
*/
public static boolean isSupportColumnConverter(Class columnType) {
if (columnType_columnConverter_map.containsKey(columnType.getName())) {
return true;
} else if (ColumnConverter.class.isAssignableFrom(columnType)) {//isAssignableFrom如果调用这个方法的class或接口 与 参数cls表示的类或接口相同,或者是参数cls表示的类或接口的父类,则返回true。
try {
ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance();
if (columnConverter != null) {
columnType_columnConverter_map.put(columnType.getName(), columnConverter);
}
return columnConverter == null;
} catch (Throwable e) {
}
}
return false;
}
4.1.2.1.1.1.2.1.1.1 标准列对象columnType_columnConverter_map内容,上述判断的依据:
private static final ConcurrentHashMap<String, ColumnConverter> columnType_columnConverter_map;
static {
columnType_columnConverter_map = new ConcurrentHashMap<String, ColumnConverter>();
BooleanColumnConverter booleanColumnConverter = new BooleanColumnConverter();
columnType_columnConverter_map.put(boolean.class.getName(), booleanColumnConverter);
columnType_columnConverter_map.put(Boolean.class.getName(), booleanColumnConverter);
ByteArrayColumnConverter byteArrayColumnConverter = new ByteArrayColumnConverter();
columnType_columnConverter_map.put(byte[].class.getName(), byteArrayColumnConverter);
ByteColumnConverter byteColumnConverter = new ByteColumnConverter();
columnType_columnConverter_map.put(byte.class.getName(), byteColumnConverter);
columnType_columnConverter_map.put(Byte.class.getName(), byteColumnConverter);
CharColumnConverter charColumnConverter = new CharColumnConverter();
columnType_columnConverter_map.put(char.class.getName(), charColumnConverter);
columnType_columnConverter_map.put(Character.class.getName(), charColumnConverter);
DateColumnConverter dateColumnConverter = new DateColumnConverter();
columnType_columnConverter_map.put(Date.class.getName(), dateColumnConverter);
DoubleColumnConverter doubleColumnConverter = new DoubleColumnConverter();
columnType_columnConverter_map.put(double.class.getName(), doubleColumnConverter);
columnType_columnConverter_map.put(Double.class.getName(), doubleColumnConverter);
FloatColumnConverter floatColumnConverter = new FloatColumnConverter();
columnType_columnConverter_map.put(float.class.getName(), floatColumnConverter);
columnType_columnConverter_map.put(Float.class.getName(), floatColumnConverter);
IntegerColumnConverter integerColumnConverter = new IntegerColumnConverter();
columnType_columnConverter_map.put(int.class.getName(), integerColumnConverter);
columnType_columnConverter_map.put(Integer.class.getName(), integerColumnConverter);
LongColumnConverter longColumnConverter = new LongColumnConverter();
columnType_columnConverter_map.put(long.class.getName(), longColumnConverter);
columnType_columnConverter_map.put(Long.class.getName(), longColumnConverter);
ShortColumnConverter shortColumnConverter = new ShortColumnConverter();
columnType_columnConverter_map.put(short.class.getName(), shortColumnConverter);
columnType_columnConverter_map.put(Short.class.getName(), shortColumnConverter);
SqlDateColumnConverter sqlDateColumnConverter = new SqlDateColumnConverter();
columnType_columnConverter_map.put(java.sql.Date.class.getName(), sqlDateColumnConverter);
StringColumnConverter stringColumnConverter = new StringColumnConverter();
columnType_columnConverter_map.put(String.class.getName(), stringColumnConverter);
}
4.1.2.1.1.1.3 获取表的ID属性TableUtils.getId(entityType);
/**
* 获得对象的ID属性
*/
static synchronized com.lidroid.xutils.db.table.Id getId(Class<?> entityType) {
if (Object.class.equals(entityType)) {
throw new RuntimeException("field 'id' not found");
}
if (entityIdMap.containsKey(entityType.getName())) {
return entityIdMap.get(entityType.getName());
}
Field primaryKeyField = null;
Field[] fields = entityType.getDeclaredFields();//获取声明字段
if (fields != null) {
for (Field field : fields) {
if (field.getAnnotation(Id.class) != null) {//获取注解ID属性
primaryKeyField = field;
break;
}
}
if (primaryKeyField == null) {//没有发现注解ID,根据字段生成ID
for (Field field : fields) {
if ("id".equals(field.getName()) || "_id".equals(field.getName())) {
primaryKeyField = field;
break;
}
}
}
}
if (primaryKeyField == null) {
return getId(entityType.getSuperclass());//没有iD属性再去他的父类去找
}
com.lidroid.xutils.db.table.Id id = new com.lidroid.xutils.db.table.Id(entityType, primaryKeyField);//生成数据ID对象
entityIdMap.put(entityType.getName(), id);//存储这个ID对象
return id;
}
4.1.2.1.1.1.3.1 ID构造函数:com.lidroid.xutils.db.table.Id id = new com.lidroid.xutils.db.table.Id(entityType, primaryKeyField);
Id(Class<?> entityType, Field field) {
super(entityType, field);
columnFieldClassName = columnField.getType().getName();//id属性类型名
}
4.1.2.1.1.1.3.1.1 父类构造函数super(entityType, field);
Column(Class<?> entityType, Field field) {
this.columnField = field;
this.columnConverter = ColumnConverterFactory.getColumnConverter(field.getType());//获取ID属性的ColumnConverter对象
this.columnName = ColumnUtils.getColumnNameByField(field);
if (this.columnConverter != null) {
this.defaultValue = this.columnConverter.getFieldValue(ColumnUtils.getColumnDefaultValue(field));
} else {
this.defaultValue = null;
}
this.getMethod = ColumnUtils.getColumnGetMethod(entityType, field);
this.setMethod = ColumnUtils.getColumnSetMethod(entityType, field);
}
至此Table对象构造完成。接下来如果数据库中的表不存在就去创建。
4.1.2.2 去构建创建表的SQL语句 SqlInfoBuilder.buildCreateTableSqlInfo(this, entityType);
public static SqlInfo buildCreateTableSqlInfo(DbUtils db, Class<?> entityType) throws DbException {
Table table = Table.get(db, entityType);
Id id = table.id;
StringBuffer sqlBuffer = new StringBuffer();//构造新建数据库SQL语句
sqlBuffer.append("CREATE TABLE IF NOT EXISTS ");
sqlBuffer.append(table.tableName);
sqlBuffer.append(" ( ");
if (id.isAutoIncrement()) {//id自增
sqlBuffer.append(""").append(id.getColumnName()).append("" ").append("INTEGER PRIMARY KEY AUTOINCREMENT,");
} else {
sqlBuffer.append(""").append(id.getColumnName()).append("" ").append(id.getColumnDbType()).append(" PRIMARY KEY,");
}
Collection<Column> columns = table.columnMap.values();//获取表的列对象集合
for (Column column : columns) {//组合列名
if (column instanceof Finder) {//主表
continue;
}
sqlBuffer.append(""").append(column.getColumnName()).append("" ");//列名
sqlBuffer.append(column.getColumnDbType());//类型
if (ColumnUtils.isUnique(column.getColumnField())) {//属性
sqlBuffer.append(" UNIQUE");
}
if (ColumnUtils.isNotNull(column.getColumnField())) {
sqlBuffer.append(" NOT NULL");
}
String check = ColumnUtils.getCheck(column.getColumnField());
if (check != null) {
sqlBuffer.append(" CHECK(").append(check).append(")");
}
sqlBuffer.append(",");
}
sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);//删除
sqlBuffer.append(" )");
return new SqlInfo(sqlBuffer.toString());
}
4.1.2.3执行构建数据表的语句 execNonQuery(sqlInfo);
public void execNonQuery(SqlInfo sqlInfo) throws DbException {
debugSql(sqlInfo.getSql());
try {
if (sqlInfo.getBindArgs() != null) {
database.execSQL(sqlInfo.getSql(), sqlInfo.getBindArgsAsArray());//有占位符的执行
} else {
database.execSQL(sqlInfo.getSql());
}
} catch (Throwable e) {
throw new DbException(e);
}
}
/**
* 获取表注解默认值
*/
public static String getExecAfterTableCreated(Class<?> entityType) {
Table table = entityType.getAnnotation(Table.class);
if (table != null) {
return table.execAfterTableCreated();
}
return null;
}
4.1.2.5 如果这个默认值语句不为空去执行,设置默认值execNonQuery(execAfterTableCreated);即调用4.1.2.3函数。
至此,对于数据表如果不存在就去创建操作完成。
4.1.3 去构造插入的SQL语句SqlInfoBuilder.buildInsertSqlInfo(this, entity);
public static SqlInfo buildInsertSqlInfo(DbUtils db, Object entity) throws DbException {
List<KeyValue> keyValueList = entity2KeyValueList(db, entity);
if (keyValueList.size() == 0) return null;
SqlInfo result = new SqlInfo();
StringBuffer sqlBuffer = new StringBuffer();
sqlBuffer.append("INSERT INTO ");
sqlBuffer.append(TableUtils.getTableName(entity.getClass()));//表名
sqlBuffer.append(" (");
for (KeyValue kv : keyValueList) {//封装插入的实体键值对
sqlBuffer.append(kv.key).append(",");
result.addBindArgWithoutConverter(kv.value);//添加到属性链表中
}
sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
sqlBuffer.append(") VALUES (");
int length = keyValueList.size();
for (int i = 0; i < length; i++) {
sqlBuffer.append("?,");
}
sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
sqlBuffer.append(")");
result.setSql(sqlBuffer.toString());
return result;
}
4.1.4 执行SQL语句执行插入数据操作 execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity));即调用4.1.2.3函数。
4.1.5 设置数据库事务提交成功setTransactionSuccessful();
private void setTransactionSuccessful() {
if (allowTransaction) {
database.setTransactionSuccessful();
}
}
至此,数据库插入一条记录完成。
5.客户端存储List数据
try {
mUserFriendDbUtils.saveAll(friends);
} catch (DbException e) {
e.printStackTrace();
}
5.1 存储List数据saveAll
public void saveAll(List<?> entities) throws DbException {
if (entities == null || entities.size() == 0) return;
try {
beginTransaction();//开启事务
createTableIfNotExist(entities.get(0).getClass());
for (Object entity : entities) {
execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity));
}
setTransactionSuccessful();
} finally {
endTransaction();
}
}
后续与上述单项插入相同。
删除数据操作。deleteAll;
6 客户端删除操作
try {
mUserCircleDbUtils.deleteAll(Circle.class);
} catch (DbException e) {
e.printStackTrace();
}
6.1 执行删除mUserCircleDbUtils.deleteAll(Circle.class);
public void deleteAll(Class<?> entityType) throws DbException {
delete(entityType, null);
}
6.1.1 调用delete(entityType, null);先判断表是否存在,在开启事务管理,执行SQL语句,提交事务成功,关闭事务。
public void delete(Class<?> entityType, WhereBuilder whereBuilder) throws DbException {
if (!tableIsExist(entityType)) return;
try {
beginTransaction();
execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(this, entityType, whereBuilder));
setTransactionSuccessful();
} finally {
endTransaction();
}
}
6.1.1.1 构造删除的SQL语句SqlInfoBuilder.buildDeleteSqlInfo(this, entityType, whereBuilder);
public static SqlInfo buildDeleteSqlInfo(DbUtils db, Class<?> entityType, WhereBuilder whereBuilder) throws DbException {
Table table = Table.get(db, entityType);//获取表对象
StringBuilder sb = new StringBuilder(buildDeleteSqlByTableName(table.tableName));
if (whereBuilder != null && whereBuilder.getWhereItemSize() > 0) {
sb.append(" WHERE ").append(whereBuilder.toString());
}
return new SqlInfo(sb.toString());
}
6.1.1.1.1根据表名构造删除SQL语句buildDeleteSqlByTableName(table.tableName)
private static String buildDeleteSqlByTableName(String tableName) {
return "DELETE FROM " + tableName;
}
接下来执行与前面相同。
至此deleteAll操作完成。
查找findAll操作:
7 客户端findAll操作:
try {
userList = mUserInforDbUtils.findAll(User.class);
} catch (DbException e) {
e.printStackTrace();
}
7.1查找操作;
public <T> List<T> findAll(Class<T> entityType) throws DbException {
return findAll(Selector.from(entityType));
}
public <T> List<T> findAll(Selector selector) throws DbException {
if (!tableIsExist(selector.getEntityType())) return null;
String sql = selector.toString();//构造选择语句
long seq = CursorUtils.FindCacheSequence.getSeq();
findTempCache.setSeq(seq);//
Object obj = findTempCache.get(sql);
if (obj != null) {//存在缓存
return (List<T>) obj;
}
List<T> result = new ArrayList<T>();
Cursor cursor = execQuery(sql);//不存在缓存去执行查询吧
if (cursor != null) {
try {
while (cursor.moveToNext()) {//存储
T entity = (T) CursorUtils.getEntity(this, cursor, selector.getEntityType(), seq);//////////
result.add(entity);
}
findTempCache.put(sql, result);
} catch (Throwable e) {
throw new DbException(e);
} finally {
IOUtils.closeQuietly(cursor);
}
}
return result;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("SELECT ");
result.append("*");
result.append(" FROM ").append(tableName);
if (whereBuilder != null && whereBuilder.getWhereItemSize() > 0) {
result.append(" WHERE ").append(whereBuilder.toString());
}
if (orderByList != null) {
for (int i = 0; i < orderByList.size(); i++) {
result.append(" ORDER BY ").append(orderByList.get(i).toString());
}
}
if (limit > 0) {
result.append(" LIMIT ").append(limit);
result.append(" OFFSET ").append(offset);
}
return result.toString();
}
7.1.1.1.1执行查找语句获得查找的数据CursorUtils.getEntity(this, cursor, selector.getEntityType(), seq);
public static <T> T getEntity(final DbUtils db, final Cursor cursor, Class<T> entityType, long findCacheSequence) {
if (db == null || cursor == null) return null;
EntityTempCache.setSeq(findCacheSequence);
try {
Table table = Table.get(db, entityType);
Id id = table.id;
String idColumnName = id.getColumnName();
int idIndex = id.getIndex();
if (idIndex < 0) {
idIndex = cursor.getColumnIndex(idColumnName);
}
Object idValue = id.getColumnConverter().getFieldValue(cursor, idIndex);
T entity = EntityTempCache.get(entityType, idValue);
if (entity == null) {
entity = entityType.newInstance();
id.setValue2Entity(entity, cursor, idIndex);
EntityTempCache.put(entityType, idValue, entity);
} else {
return entity;
}
int columnCount = cursor.getColumnCount();
for (int i = 0; i < columnCount; i++) {
String columnName = cursor.getColumnName(i);
Column column = table.columnMap.get(columnName);
if (column != null) {
column.setValue2Entity(entity, cursor, i);
}
}
// init finder
for (Finder finder : table.finderMap.values()) {
finder.setValue2Entity(entity, null, 0);
}
return entity;
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
return null;
}
执行完查询之后缓存并返回结果。
更新操作
8 客户端调用更新
try {
mArticleDbUtils.update(acceptArticle, "zanCount");
} catch (DbException e) {
e.printStackTrace();
}
8.1 函数update
public void update(Object entity, String... updateColumnNames) throws DbException {
if (!tableIsExist(entity.getClass())) return;
try {
beginTransaction();
execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity, updateColumnNames));
setTransactionSuccessful();
} finally {
endTransaction();
}
}
8.1.1构造更新SQL语句SqlInfoBuilder.buildUpdateSqlInfo(this, entity, updateColumnNames)
public static SqlInfo buildUpdateSqlInfo(DbUtils db, Object entity, String... updateColumnNames) throws DbException {
List<KeyValue> keyValueList = entity2KeyValueList(db, entity);
if (keyValueList.size() == 0) return null;
HashSet<String> updateColumnNameSet = null;
if (updateColumnNames != null && updateColumnNames.length > 0) {
updateColumnNameSet = new HashSet<String>(updateColumnNames.length);
Collections.addAll(updateColumnNameSet, updateColumnNames);
}
Class<?> entityType = entity.getClass();
Table table = Table.get(db, entityType);
Id id = table.id;
Object idValue = id.getColumnValue(entity);
if (null == idValue) {
throw new DbException("this entity[" + entity.getClass() + "]'s id value is null");
}
SqlInfo result = new SqlInfo();
StringBuffer sqlBuffer = new StringBuffer("UPDATE ");
sqlBuffer.append(table.tableName);
sqlBuffer.append(" SET ");
for (KeyValue kv : keyValueList) {
if (updateColumnNameSet == null || updateColumnNameSet.contains(kv.key)) {
sqlBuffer.append(kv.key).append("=?,");
result.addBindArgWithoutConverter(kv.value);
}
}
sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
sqlBuffer.append(" WHERE ").append(WhereBuilder.b(id.getColumnName(), "=", idValue));
result.setSql(sqlBuffer.toString());
return result;
}
后续操作与前面相同,支持更新操作完成。
二 致敬原作者,谢谢作者辛苦付出,代码受益匪浅。
传送门
三 其他讲解:
架构讲解:传送门
四 源码注释
源码详细注释:传送门
- XUtils 源码分析(三)--数据库操作模块
- XUtils 源码分析(一)--网络操作模块
- android Xutils 数据库操作源码分析
- XUtils 源码分析(二)--图片缓存模块
- xUtils -- view模块分析
- XUtils源码分析之HttpUtils(一)
- XUtils BitmapUtils 源码分析
- 根据源码解析xUtils 3.x数据库update操作
- XUtils数据库的操作
- xUtils之操作数据库
- Xutils 3.0+数据库操作
- android Xutils Http模块分析
- Android4.4.2源码分析之WiFi模块(三)
- xUtils异步HTTP源码分析
- xUtils源码分析系列1
- derby数据库源码分析(三)–页面分析
- xUtils 的 数据库操作类
- AMPS:MySQL数据库操作模块源码解读
- AutoLayout 和 autoresizing
- iOS 无线部署
- SVN学习总结(1)——SVN简介及入门使用
- WebService 类文件内容 RevitUpload
- [Java] 如何讓字串前自動補上 0
- XUtils 源码分析(三)--数据库操作模块
- 237. Delete Node in a Linked List
- JPA入门例子(采用JPA的hibernate实现版本)
- 欢迎使用CSDN-markdown编辑器
- poj3114Countries in War(强连通缩点+最短路)
- VS2010 如何更改对话框界面风格为win7风格
- 二维凸包模板 【Graham扫描算法】
- oracl数据库之创建表空间
- tiny4412预装apk