android小问题--------------------SQLiteDatabase.insert(table, nullColumnHack, values)参数

本文详细解析 SQLiteDatabase 的插入操作方法,包括 execSQL() 和 .insert() 方法的区别及使用方式,通过源码分析理解底层逻辑,以及 nullColumnHack 参数的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SQLiteDatabase除了可以通过execSQL()直接执行SQL语句之外,还可以通过.insert(table, nullColumnHack, values)方法直接插入操作。

第一个参数为表名,第三个参数为ContentValues实例,以键值对的形式将列和值Put进去然后放入第三个参数为就行了。

那么第二个参数是什么意思,总有人搞不明白,第二个参数的字面意思其实就是:当第三个参数传入null时,第二个参数为什么。也就是说如果第三个参数不为null,那么第二个参数是不起作用的。那这又是为什么,看源码:

因为底层Insert()方法直接调用了insertWithOnConflict()方法,那么就直接贴此方法的源码:

 acquireReference();
        try {
            StringBuilder sql = new StringBuilder();
            sql.append("INSERT");
            sql.append(CONFLICT_VALUES[conflictAlgorithm]);
            sql.append(" INTO ");
            sql.append(table);
            sql.append('(');

            Object[] bindArgs = null;
            int size = (initialValues != null && initialValues.size() > 0)
                    ? initialValues.size() : 0;
            if (size > 0) {
                bindArgs = new Object[size];
                int i = 0;
                for (String colName : initialValues.keySet()) {
                    sql.append((i > 0) ? "," : "");
                    sql.append(colName);
                    bindArgs[i++] = initialValues.get(colName);
                }
                sql.append(')');
                sql.append(" VALUES (");
                for (i = 0; i < size; i++) {
                    sql.append((i > 0) ? ",?" : "?");
                }
            } else {
                sql.append(nullColumnHack + ") VALUES (NULL");
            }
            sql.append(')');

可以看到,此方法其实在底层也是拼接了SQL串。。。所以我说不如直接去学学SQL。。要不不懂SQL的人根本不明白为什么。。其实底层逻辑是这样的,它会根据三个参数拼接出这样的sql语句 insert into tableNmae (......) values(......)  values中的值就由传入的第三个参数拼接出来的,而我们可以看到,如果第三个值传入为Null,那么去执行 

sql.append(nullColumnHack + ") VALUES (NULL");
也就是是说最后拼接出来的SQL为:insert into tableName(null)values(null),这样sql语法就错误的。。会报错。。所以。。就是这样的。


package com.example.myapplication; import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import androidx.annotation.Nullable; public class UserDbHelper extends SQLiteOpenHelper { private static UserDbHelper sHelper; private static final String DB_NAME = "user.db"; //数据库名 private static final int VERSION = 1; //版本号 //必须实现其中一个构方法 public UserDbHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } //创建单例,供使用调用该类里面的的增删改查的方法 public synchronized static UserDbHelper getInstance(Context context) { if (null == sHelper) { sHelper = new UserDbHelper(context, DB_NAME, null, VERSION); } return sHelper; } @Override public void onCreate(SQLiteDatabase db) { //创建user_table表 db.execSQL("create table user_table(user_id integer primary key autoincrement, " + "username text," + //用户名 "password text," + //密码 "nickname text" + // ")"); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } /** * 登录 */ @SuppressLint("Range") public UserInfo login(String username) { //获取SQLiteDatabase实例 SQLiteDatabase db = getReadableDatabase(); UserInfo userInfo = null; String sql = "select user_id,username,password,nickname from user_table where username=?"; String[] selectionArgs = {username}; Cursor cursor = db.rawQuery(sql, selectionArgs); if (cursor.moveToNext()) { int user_id = cursor.getInt(cursor.getColumnIndex("user_id")); String name = cursor.getString(cursor.getColumnIndex("username")); String password = cursor.getString(cursor.getColumnIndex("password")); String nickname = cursor.getString(cursor.getColumnIndex("nickname")); userInfo = new UserInfo(user_id, name, password, nickname); } cursor.close(); db.close(); return userInfo; } /** * 注册 */ public int register(String username, String password, String nickname) { //获取SQLiteDatabase实例 SQLiteDatabase db = getWritableDatabase(); ContentValues values = new ContentValues(); //填充占位符 values.put("username", username); values.put("password", password); values.put("nickname", nickname); String nullColumnHack = "values(null,?,?,?)"; //执行 int insert = (int) db.insert("user_table", nullColumnHack, values); // db.close(); return insert; } public int updatePassword(String username, String newPassword) { return ; } }
最新发布
06-24
<think>我们已经在之前的回答中给出了updatePassword方法的实现,现在结合用户提供的引用和上下文,给出更详细的说明和实现步骤。根据引用[3],我们使用SQLiteOpenHelper类,并且会用到getWritableDatabase()方法获取可写数据库。同时,引用[4]提到了使用rawQuery进行查询,但更新操作我们使用update方法。目标:在UserDbHelper类中实现updatePassword方法,用于更新指定用户名的密码。步骤:1.获取可写数据库实例。2.创建ContentValues对象,用于存放要更新的字段(密码)。3.指定WHERE条件(根据用户名更新),使用占位符防止SQL注入。4.执行更新操作,并返回受影响的行数。具体代码实现如下:</think>### 在Android Studio中实现`updatePassword`方法 以下是完整的`updatePassword`方法实现,用于更新`user_table`表中的密码字段: ```java public int updatePassword(String username, String newPassword) { // 1. 获取可写数据库实例 SQLiteDatabase db = getWritableDatabase(); // 2. 创建ContentValues存放新密码 ContentValues values = new ContentValues(); values.put("password", newPassword); // 3. 设置WHERE条件(防止SQL注入) String whereClause = "username = ?"; String[] whereArgs = {username}; // 4. 执行更新操作 int rowsAffected = db.update( "user_table", // 要更新的表名 values, // 包含新字段值的ContentValues whereClause, // WHERE条件(带占位符) whereArgs // WHERE条件的参数); // 5. 关闭数据库连接 db.close(); // 6. 返回受影响的行数 return rowsAffected; } ``` ### 关键点说明: 1. **安全更新机制**: - 使用参数化查询(`?`占位符)避免SQL注入攻击[^1] - `ContentValues`确保类型安全的数据封装[^3] 2. **`db.update()`方法参数**: | 参数 | 说明 | |------|------| | `"user_table"` | 要更新的表名 | | `values` | 包含新字段值的ContentValues对象 | | `whereClause` | WHERE条件(`username = ?`) | | `whereArgs` | 替换WHERE条件中`?`的实际值 | 3. **返回值处理**: - 返回`int`类型表示受影响的行数 - `0` = 未找到匹配用户 - `1` = 成功更新一个用户 - `>1` = 更新了多个用户(需确保username唯一) 4. **密码安全强化(推荐)**: ```java // 添加密码哈希处理(需实现BCryptUtil) String hashedPassword = BCryptUtil.hashPassword(newPassword); values.put("password", hashedPassword); ``` ### 完整类实现参考: ```java public class UserDbHelper extends SQLiteOpenHelper { // ... 其他代码不变 ... public int updatePassword(String username, String newPassword) { SQLiteDatabase db = getWritableDatabase(); ContentValues values = new ContentValues(); values.put("password", newPassword); // 或使用哈希后的密码 int result = db.update("user_table", values, "username=?", new String[]{username}); db.close(); return result; } } ``` ### 使用方法示例: ```java // 在Activity中调用更新密码 UserDbHelper dbHelper = UserDbHelper.getInstance(context); int updateResult = dbHelper.updatePassword("user123", "newPassword123"); if (updateResult > 0) { // 更新成功 Toast.makeText(this, "密码更新成功", Toast.LENGTH_SHORT).show(); } else { // 用户不存在 Toast.makeText(this, "用户不存在,请检查用户名", Toast.LENGTH_SHORT).show(); } ``` ### 最佳实践建议: 1. **事务处理**:批量操作时使用事务提升性能 ```java db.beginTransaction(); try { // 执行更新操作 db.setTransactionSuccessful(); } finally { db.endTransaction(); } ``` 2. **输入验证**:在调用前验证用户名和新密码有效性 3. **错误处理**:添加`try-catch`处理数据库异常 4. **密码加密**:存储前对密码进行哈希处理(推荐BCrypt)[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值