Android Studio连接MSSQL成功但无法存储注册数据求助
问题
我是一名正在学习SQL的学生,通过YouTube教程实现Android Studio与MSSQL服务器的连接,APP的TextView显示连接状态正常,但点击注册按钮后,注册数据无法写入MSSQL数据库的register表,表始终为空。以下是我的Register.java代码:
package com.example.login; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import android.Manifest; import android.annotation.SuppressLint; import android.app.DatePickerDialog; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.AsyncTask; import android.os.Bundle; import android.os.StrictMode; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.DatePicker; import android.widget.EditText; import android.widget.RadioGroup; import android.widget.TextView; import android.widget.Toast; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.Calendar; public class Register extends AppCompatActivity { private static String ip = "192.168.1.5"; private static String port = "1433"; private static String Classes = "net.sourceforge.jtds.jdbc.Driver"; private static String db = "DB_SWEENEY_USERS"; private static String un = "depota"; private static String pass = "1234"; Connection con; Statement stmt; private TextView txtView1; private EditText InputFirstName; private EditText InputLastName; private EditText InputPassword; private EditText InputEmail; private static final String TAG = "Register"; private TextView txtViewPickDate; private DatePickerDialog.OnDateSetListener mDateSetListener; public static final String PERSON_NAME = "com.name.MESSAGE"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register2); RadioGroup rdGroup = findViewById(R.id.rdGroup); rdGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { String gender; switch (i){ case R.id.maleBtn: gender = "Male"; break; case R.id.femaleBtn: gender = "Female"; break; } } }); //CHOOSE MALE AND FEMALE txtViewPickDate = findViewById(R.id.txtViewPickDate); txtViewPickDate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Calendar cal = Calendar.getInstance(); int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH); int day = cal.get(Calendar.DAY_OF_MONTH); DatePickerDialog dialog = new DatePickerDialog(Register.this, android.R.style.Theme_Holo_Light_Dialog_MinWidth, mDateSetListener,year,month,day); dialog.show(); } });//DATE PICKER mDateSetListener = new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker datePicker, int year, int month, int day) { month = month +1; Log.d(TAG, "onDateSet:mm/dd/yyy: " + month + "/" + day + "/" + year); String date = month + "/" + day + "/" + year; txtViewPickDate.setText(date); } };//DISPLAY DATE PICKER InputFirstName = findViewById(R.id.InputFirstName); InputLastName = findViewById(R.id.InputLastName); InputPassword = findViewById(R.id.InputPassword); InputEmail = findViewById(R.id.InputEmail); EditText InputConfirmPassword = findViewById(R.id.InputConfirmPassword); txtView1 = findViewById(R.id.txtView1); Button regBtn = findViewById(R.id.regBtn); regBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new Register.registerUser().execute(""); /* String password = InputPassword.getText().toString(); String confirm = InputConfirmPassword.getText().toString(); if(TextUtils.isEmpty(password) || TextUtils.isEmpty(confirm)) { Toast.makeText(Register.this, "Password field is empty!", Toast.LENGTH_SHORT).show(); } else if(password.equals(confirm)) { Intent intent = new Intent(Register.this, Main_Menu.class); String personName = InputFirstName.getText().toString() + " " + InputLastName.getText().toString(); intent.putExtra(PERSON_NAME, personName); startActivity(intent); } else { Toast.makeText(Register.this, "Password don't match", Toast.LENGTH_SHORT).show(); }*/ } }); } public class registerUser extends AsyncTask<String, String, String>{ String z = ""; Boolean isSuccess= false; @Override protected void onPreExecute() { txtView1.setText("Sending Data to Datbase"); } @Override protected void onPostExecute(String s) { txtView1.setText("Registration Successful"); InputFirstName.setText(""); InputLastName.setText(""); InputPassword.setText(""); InputEmail.setText(""); } @Override protected String doInBackground(String... strings) { try { con = connectionClass(un.toString(), pass.toString(),db.toString(),ip.toString()); if (con==null){ z = "ERROR DEPOTA NA ANO NI MAN"; }else{ String sql = "INSERT INTO register (firstName,lastName,middleInitial,gender,bDate,uName,email,pass) VALUES ('"+InputFirstName.getText()+"','"+InputLastName.getText()+"','"+"NULL"+"','"+"NULL"+"','"+"NULL"+"','"+"NULL"+"','"+InputEmail.getText()+"','"+InputPassword.getText()+"')"; stmt = con.createStatement(); stmt.executeUpdate(sql); } }catch (Exception e){ isSuccess = false; z = e.getMessage(); } return z; } } @SuppressLint("NewApi") public Connection connectionClass(String user, String password, String database, String server){ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); Connection connection = null; String connectionURL = null; try { Class.forName("net.sourceforge.jtds.jdbc.Driver"); connectionURL = "jdbc:jtds:sqlserver://" +server+"/" +database+";user=" + user+";password=" +password + ";"; connection = DriverManager.getConnection(connectionURL); } catch (Exception e) { Log.e("SQL Connection Error", e.getMessage()); } return connection; } }
排查与修复方案
1. 核心SQL语句错误
- 未获取输入文本:原代码直接拼接
InputFirstName.getText(),未调用toString(),实际插入的是EditText对象的内存地址而非用户输入内容,需改为InputFirstName.getText().toString().trim()。 - 错误处理NULL值:原代码将
NULL用单引号包裹,变成字符串'NULL',而非SQL的空值。若数据库字段不允许该字符串格式,会导致插入失败,需用PreparedStatement的setNull()方法处理空值。
2. 错误反馈缺失
原onPostExecute方法不管插入成功与否都显示“Registration Successful”,无法获取实际错误信息。修改后根据isSuccess状态显示结果,并通过Toast提示错误详情,方便排查问题。
3. 未收集完整用户数据
原代码未保存性别和出生日期的选择结果,导致这两个字段无法插入数据库。新增selectedGender和selectedBirthDate变量存储用户选择值,并在SQL中传入。
4. 连接字符串遗漏端口
原代码定义了port变量但未使用,需将连接地址改为ip + ":" + port,确保连接到正确的数据库端口。
5. 避免SQL注入风险
使用PreparedStatement替代Statement,既可以避免SQL注入,也能简化参数拼接逻辑,减少语法错误。
修复后的关键代码片段
public class Register extends AppCompatActivity { // 新增变量保存性别和出生日期 private String selectedGender = null; private String selectedBirthDate = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register2); // 修改RadioGroup监听,保存性别选择 RadioGroup rdGroup = findViewById(R.id.rdGroup); rdGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { switch (i){ case R.id.maleBtn: selectedGender = "Male"; break; case R.id.femaleBtn: selectedGender = "Female"; break; default: selectedGender = null; } } }); // 修改日期选择监听,保存出生日期 mDateSetListener = new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker datePicker, int year, int month, int day) { month = month +1; Log.d(TAG, "onDateSet:mm/dd/yyy: " + month + "/" + day + "/" + year); selectedBirthDate = month + "/" + day + "/" + year; txtViewPickDate.setText(selectedBirthDate); } }; // 注册按钮点击事件,新增必填字段校验 regBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (TextUtils.isEmpty(InputFirstName.getText().toString()) || TextUtils.isEmpty(InputEmail.getText().toString()) || TextUtils.isEmpty(InputPassword.getText().toString())) { Toast.makeText(Register.this, "必填字段不能为空", Toast.LENGTH_SHORT).show(); return; } new registerUser().execute(""); } }); } public class registerUser extends AsyncTask<String, String, String> { String z = ""; Boolean isSuccess = false; @Override protected void onPostExecute(String s) { if (isSuccess) { txtView1.setText("Registration Successful"); InputFirstName.setText(""); InputLastName.setText(""); InputPassword.setText(""); InputEmail.setText(""); txtViewPickDate.setText(""); selectedGender = null; } else { txtView1.setText("Registration Failed: " + s); Toast.makeText(Register.this, "错误信息: " + s, Toast.LENGTH_LONG).show(); } } @Override protected String doInBackground(String... strings) { try { // 加入端口号 con = connectionClass(un, pass, db, ip + ":" + port); if (con == null) { z = "无法连接到数据库"; } else { // 使用PreparedStatement插入数据 String sql = "INSERT INTO register (firstName, lastName, middleInitial, gender, bDate, uName, email, pass) " + "VALUES (?, ?, NULL, ?, ?, NULL, ?, ?)"; PreparedStatement pstmt = con.prepareStatement(sql); pstmt.setString(1, InputFirstName.getText().toString().trim()); pstmt.setString(2, InputLastName.getText().toString().trim()); // 处理性别空值 if (selectedGender != null) { pstmt.setString(3, selectedGender); } else { pstmt.setNull(3, java.sql.Types.VARCHAR); } // 处理出生日期空值 if (selectedBirthDate != null) { pstmt.setString(4, selectedBirthDate); } else { pstmt.setNull(4, java.sql.Types.VARCHAR); } pstmt.setString(5, InputEmail.getText().toString().trim()); pstmt.setString(6, InputPassword.getText().toString().trim()); int affectedRows = pstmt.executeUpdate(); if (affectedRows > 0) { isSuccess = true; z = "数据插入成功"; } else { z = "未插入任何数据"; } pstmt.close(); con.close(); } } catch (Exception e) { isSuccess = false; z = e.getMessage(); Log.e("Register Error", z); } return z; } } }
额外检查项
- 确认MSSQL用户
depota拥有register表的INSERT权限。 - 检查
register表的字段类型与插入数据是否匹配(例如email字段长度是否足够,bDate字段是否支持字符串格式日期)。 - 查看MSSQL的错误日志,确认是否有插入操作的报错记录。
内容的提问来源于stack exchange,提问作者seyan
相关产品推荐
相关产品推荐

