Android 连接 SQL Server (jtds方式)——下
本文主要补充介绍jtds的查询方法,将以博主的一个实际开发程序进行说明
下图是项目的文件列表与界面效果:
运行效果:
1、三个EditText对应的是单个计划的序号、品种名、数量
2、填入三个数据后,点击“增加”,Insert到数据库中
3、填入三个数据后,点击“修改”,根据序号,Update数据库中的品种名、数量
4、填入序号后,点击“删除”,根据序号,Delete数据库中的一行记录
5、点击“查询全部”,在下方GridView中显示整个表格的记录
6、点击“清空”,三个EditText的内容清空,GridView的内容清空
数据库信息:
1、数据库名:SYSTEM TEST
2、用户名:sa
3、密码:123
4、表名:DayPlan
5、字段1:ID,nvarchar =>表示序号
6、字段2:PCBA,nvarchar =>表示品种名
7、字段3:AMOUNT,nvarchar =>数量
AndroidManifest.xml:
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="com.test.androidsqltest"
4 android:versionCode="1"
5 android:versionName="1.0" >
6
7 <uses-permission android:name="android.permission.INTERNET" />
8
9 <uses-sdk
10 android:minSdkVersion="14"
11 android:targetSdkVersion="21" />
12
13 <application
14 android:allowBackup="true"
15 android:icon="@drawable/ic_launcher"
16 android:label="@string/app_name"
17 android:theme="@style/AppTheme" >
18 <activity
19 android:name=".MainActivity"
20 android:label="@string/app_name" >
21 <intent-filter>
22 <action android:name="android.intent.action.MAIN" />
23
24 <category android:name="android.intent.category.LAUNCHER" />
25 </intent-filter>
26 </activity>
27 </application>
28
29 </manifest>
插入网络操作权限
strings.xml:
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3
4 <string name="app_name">AndroidSqlTest</string>
5 <string name="action_settings">Settings</string>
6 <string name="id">序 号:</string>
7 <string name="pcb">机种名:</string>
8 <string name="amount">数 量:</string>
9 <string name="insert">增加</string>
10 <string name="update">修改</string>
11 <string name="delete">删除</string>
12 <string name="clear">清空</string>
13 <string name="select">查询全部</string>
14
15 </resources>
activity_main.xml:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:paddingBottom="@dimen/activity_vertical_margin"
6 android:paddingLeft="@dimen/activity_horizontal_margin"
7 android:paddingRight="@dimen/activity_horizontal_margin"
8 android:paddingTop="@dimen/activity_vertical_margin"
9 tools:context="com.test.androidsqltest.MainActivity" >
10
11 <TextView
12 android:id="@+id/tvId"
13 android:layout_width="wrap_content"
14 android:layout_height="wrap_content"
15 android:layout_marginStart="10dp"
16 android:layout_marginLeft="10dp"
17 android:layout_marginTop="5dp"
18 android:text="@string/id" />
19
20 <TextView
21 android:id="@+id/tvPcb"
22 android:layout_width="wrap_content"
23 android:layout_height="wrap_content"
24 android:layout_marginStart="10dp"
25 android:layout_marginLeft="10dp"
26 android:layout_marginTop="45dp"
27 android:text="@string/pcb" />
28
29 <TextView
30 android:id="@+id/tvAmount"
31 android:layout_width="wrap_content"
32 android:layout_height="wrap_content"
33 android:layout_marginStart="10dp"
34 android:layout_marginLeft="10dp"
35 android:layout_marginTop="85dp"
36 android:text="@string/amount" />
37
38 <EditText
39 android:id="@+id/etId"
40 android:layout_width="wrap_content"
41 android:layout_height="wrap_content"
42 android:layout_marginStart="70dp"
43 android:layout_marginLeft="70dp"
44 android:layout_marginTop="-5dp"
45 android:inputType="text"
46 android:ems="10" >
47
48 <requestFocus />
49 </EditText>
50
51 <EditText
52 android:id="@+id/etPcb"
53 android:layout_width="wrap_content"
54 android:layout_height="wrap_content"
55 android:layout_marginStart="70dp"
56 android:layout_marginLeft="70dp"
57 android:layout_marginTop="35dp"
58 android:inputType="text"
59 android:ems="10" />
60
61 <EditText
62 android:id="@+id/etAmount"
63 android:layout_width="wrap_content"
64 android:layout_height="wrap_content"
65 android:layout_marginStart="70dp"
66 android:layout_marginLeft="70dp"
67 android:layout_marginTop="75dp"
68 android:inputType="text"
69 android:ems="10" />
70
71 <Button
72 android:id="@+id/btnInsert"
73 android:layout_width="80dp"
74 android:layout_height="40dp"
75 android:layout_marginStart="5dp"
76 android:layout_marginLeft="5dp"
77 android:layout_marginTop="120dp"
78 android:text="@string/insert" />
79
80 <Button
81 android:id="@+id/btnUpdate"
82 android:layout_width="80dp"
83 android:layout_height="40dp"
84 android:layout_marginStart="105dp"
85 android:layout_marginLeft="105dp"
86 android:layout_marginTop="120dp"
87 android:text="@string/update" />
88
89 <Button
90 android:id="@+id/btnDelete"
91 android:layout_width="80dp"
92 android:layout_height="40dp"
93 android:layout_marginStart="205dp"
94 android:layout_marginLeft="205dp"
95 android:layout_marginTop="120dp"
96 android:text="@string/delete" />
97
98 <Button
99 android:id="@+id/btnClear"
100 android:layout_width="120dp"
101 android:layout_height="40dp"
102 android:layout_marginStart="5dp"
103 android:layout_marginLeft="5dp"
104 android:layout_marginTop="180dp"
105 android:text="@string/clear" />
106
107 <Button
108 android:id="@+id/btnSelect"
109 android:layout_width="120dp"
110 android:layout_height="40dp"
111 android:layout_marginStart="165dp"
112 android:layout_marginLeft="165dp"
113 android:layout_marginTop="180dp"
114 android:text="@string/select" />
115
116 <GridView
117 android:id="@+id/gv"
118 android:layout_width="match_parent"
119 android:layout_height="wrap_content"
120 android:layout_centerHorizontal="true"
121 android:layout_marginTop="240dp"
122 android:numColumns="1"
123 android:verticalSpacing="15dp" >
124 </GridView>
125
126 </RelativeLayout>
planlist.xml:
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="horizontal"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent" >
6
7 <TextView android:id="@+id/header1"
8 android:layout_height="wrap_content"
9 android:layout_width="60px"
10 android:layout_marginLeft="0px"
11 android:textColor="#000000"
12 android:text="">
13 </TextView>
14
15 <TextView android:id="@+id/header2"
16 android:layout_height="wrap_content"
17 android:layout_width="180px"
18 android:layout_marginLeft="0px"
19 android:textColor="#000000"
20 android:text="">
21 </TextView>
22
23 <TextView android:id="@+id/header3"
24 android:layout_height="wrap_content"
25 android:layout_width="80px"
26 android:layout_marginLeft="0px"
27 android:textColor="#000000"
28 android:text="">
29 </TextView>
30
31 </LinearLayout>
这是GridView中单个item的布局,即一行记录有3个TextView
SqlHelper.java:
1 package MyJtds;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.PreparedStatement;
6 import java.sql.ResultSet;
7 import java.sql.ResultSetMetaData;
8 import java.sql.SQLException;
9 import java.util.List;
10
11 import org.json.JSONArray;
12 import org.json.JSONObject;
13
14 public class SqlHelper {
15 private String drive = "net.sourceforge.jtds.jdbc.Driver";
16 private String connStr;
17 private String server;
18 private String dbName;
19 private String userName;
20 private String userPwd;
21 private Connection con;
22 private PreparedStatement pstm;
23
24 public SqlHelper(String server, String dbName, String userName, String userPwd) {
25 this.server = server;
26 this.dbName = dbName;
27 this.connStr = "jdbc:jtds:sqlserver://" + this.server + ":1433/" + this.dbName;
28 this.userName = userName;
29 this.userPwd = userPwd;
30
31 try {
32 Class.forName(drive);
33 } catch (ClassNotFoundException e) {
34 // TODO Auto-generated catch block
35 e.printStackTrace();
36 }
37 }
38
39 public int ExecuteNonQuery(String sql, List<Object> params) {
40 try {
41 con = DriverManager.getConnection(this.connStr, this.userName, this.userPwd);
42 pstm = con.prepareStatement(sql);
43 if (params != null && !params.equals("")) {
44 for (int i = 0; i < params.size(); i++) {
45 pstm.setObject(i + 1, params.get(i));
46 }
47 }
48 return pstm.executeUpdate();
49 } catch (Exception e) {
50 // TODO: handle exception
51 e.printStackTrace();
52 return -1;
53 } finally {
54 try {
55 pstm.close();
56 con.close();
57 } catch (SQLException e) {
58 // TODO Auto-generated catch block
59 e.printStackTrace();
60 }
61 }
62 }
63
64 public String ExecuteQuery(String sql, List<Object> params) {
65 // TODO Auto-generated method stub
66 JSONArray jsonArray = new JSONArray();
67 try {
68 con = DriverManager.getConnection(this.connStr, this.userName, this.userPwd);
69 pstm = con.prepareStatement(sql);
70 if (params != null && !params.equals("")) {
71 for (int i = 0; i < params.size(); i++) {
72 pstm.setObject(i + 1, params.get(i));
73 }
74 }
75 ResultSet rs = pstm.executeQuery();
76 ResultSetMetaData rsMetaData = rs.getMetaData();
77 while (rs.next()) {
78 JSONObject jsonObject = new JSONObject();
79 for (int i = 0; i < rsMetaData.getColumnCount(); i++) {
80 String columnName = rsMetaData.getColumnLabel(i + 1);
81 String value = rs.getString(columnName);
82 jsonObject.put(columnName, value);
83 }
84 jsonArray.put(jsonObject);
85 }
86 return jsonArray.toString();
87 } catch (Exception e) {
88 // TODO: handle exception
89 return null;
90 } finally {
91 try {
92 pstm.close();
93 con.close();
94 } catch (SQLException e) {
95 // TODO Auto-generated catch block
96 e.printStackTrace();
97 }
98 }
99 }
100 }
Plan.java:
1 package Models;
2
3 public class Plan {
4 public String id;
5
6 public String pcb;
7
8 public String amount;
9
10 public String getId() {
11 return id;
12 }
13
14 public void setId(String id) {
15 this.id = id;
16 }
17
18 public String getPcb() {
19 return pcb;
20 }
21
22 public void setPcb(String pcb) {
23 this.pcb = pcb;
24 }
25
26 public String getAmount() {
27 return amount;
28 }
29
30 public void setAmount(String amount) {
31 this.amount = amount;
32 }
33 }
MainActivity.java:
1 package com.test.androidsqltest;
2
3 import java.lang.reflect.Type;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8
9 import com.google.gson.Gson;
10 import com.google.gson.reflect.TypeToken;
11
12 import Models.Plan;
13 import MyJtds.SqlHelper;
14 import android.annotation.SuppressLint;
15 import android.app.Activity;
16 import android.os.Bundle;
17 import android.os.Handler;
18 import android.os.Message;
19 import android.view.Menu;
20 import android.view.MenuItem;
21 import android.view.View;
22 import android.view.View.OnClickListener;
23 import android.widget.Button;
24 import android.widget.EditText;
25 import android.widget.GridView;
26 import android.widget.SimpleAdapter;
27 import android.widget.Toast;
28
29 public class MainActivity extends Activity {
30
31 // 定义控件
32 private EditText etId;
33 private EditText etPcb;
34 private EditText etAmount;
35 private Button btnInsert;
36 private Button btnUpdate;
37 private Button btnDelete;
38 private Button btnClear;
39 private Button btnSelect;
40 private GridView gv;
41 // 定义变量
42 private String id = "";
43 private String pcb = "";
44 private String amount = "";
45 // SQL帮助类,参数用于设置连接字符串,参数1:主机ip,参数2:数据库名,参数3:用户名,参数4:用户密码
46 private SqlHelper sh = new SqlHelper("192.168.1.1", "SYSTEM TEST", "sa", "123");
47
48 @Override
49 protected void onCreate(Bundle savedInstanceState) {
50 super.onCreate(savedInstanceState);
51 setContentView(R.layout.activity_main);
52
53 // 找到变量,并且赋值
54 etId = (EditText) findViewById(R.id.etId);
55 etPcb = (EditText) findViewById(R.id.etPcb);
56 etAmount = (EditText) findViewById(R.id.etAmount);
57 btnInsert = (Button) findViewById(R.id.btnInsert);
58 btnUpdate = (Button) findViewById(R.id.btnUpdate);
59 btnDelete = (Button) findViewById(R.id.btnDelete);
60 btnClear = (Button) findViewById(R.id.btnClear);
61 btnSelect = (Button) findViewById(R.id.btnSelect);
62 gv = (GridView) findViewById(R.id.gv);
63
64 // 绑定按钮的click事件监听,click事件触发后,运行clickEvent()方法
65 // 绑定的方式都是clickEvent(),到时在方法体中判断按下的是哪个按键
66 btnInsert.setOnClickListener(clickEvent());
67 btnUpdate.setOnClickListener(clickEvent());
68 btnDelete.setOnClickListener(clickEvent());
69 btnClear.setOnClickListener(clickEvent());
70 btnSelect.setOnClickListener(clickEvent());
71 }
72
73 // clickEvent()
74 private OnClickListener clickEvent() {
75 // TODO Auto-generated method stub
76 return new OnClickListener() {
77
78 // clickEvent()方法体,参数是控件的基类View,必须加上final
79 @Override
80 public void onClick(final View view) {
81 // TODO Auto-generated method stub
82 // 用view来判断按下的哪个按钮
83 if (view == btnClear) {
84 // ClearEdit()方法用于复位控件
85 ClearEdit();
86 } else {
87 // 如果不是btnClear,那就是增删改查的按钮,必须开启新的线程进行操作
88 Thread thread = new Thread(new Runnable() {
89 @Override
90 public void run() {
91 // TODO Auto-generated method stub
92 // 通过Message类来传递结果值,先实例化
93 Message msg = Message.obtain();
94 // 下面分别是增删改查方法
95 if (view == btnInsert) {
96 // 设定msg的类型,用what属性,便于后面的代码区分返回的结果是什么类型
97 // 这里的1是指操作是否成功,String
98 // 这里的2是指查询的结果,String,用json的形式表示
99 msg.what = 1;
100 msg.obj = Insert();
101 } else if (view == btnUpdate) {
102 msg.what = 1;
103 msg.obj = Update();
104 } else if (view == btnDelete) {
105 msg.what = 1;
106 msg.obj = Delete();
107 } else if (view == btnSelect) {
108 String jsonResult = Select();
109 msg.what = 2;
110 msg.obj = jsonResult;
111 } else {
112
113 }
114 // 执行完以后,把msg传到handler,并且触发handler的响应方法
115 handler.sendMessage(msg);
116 }
117 });
118 // 进程开始,这行代码不要忘记
119 thread.start();
120 }
121 }
122 };
123 }
124
125 // Handler类用于接收Message的值,并且其父类有一个默认的handleMessage方法,用super。handleMessage()方法,传入msg,就能控制主线程的控件了
126 @SuppressLint("HandlerLeak")
127 private Handler handler = new Handler() {
128 public void handleMessage(Message msg) {
129 // 调用super的方法,传入handler对象接收到的msg对象
130 super.handleMessage(msg);
131 // 判断msg.what的值,有1和2,
132 // 1表示操作是否成功,2表示查询时得到的json结果
133 switch (msg.what) {
134 case 1:
135 // 获得执行的结果,String字符串,返回操作是否成功提示
136 String rst = msg.obj.toString();
137 // 使用气泡提示
138 Toast.makeText(getApplicationContext(), rst, Toast.LENGTH_SHORT).show();
139 break;
140 case 2:
141 // 获得查询的json结果
142 String jsonResult = msg.obj.toString();
143 // 控制台输出,用于监视,与实际使用无关
144 System.out.println(jsonResult);
145
146 // Gson类,用于json的转类型操作
147 Gson gson = new Gson();
148 // 定义查询到的结果类型,每一行记录映射为对象,本程序查询的是生产计划,所以一行记录表示一个品种的生产计划,用Plan类表示,用List收集全部Plan类
149 Type type = new TypeToken<List<Plan>>() {
150 }.getType();
151 // 使用gson的fromJson()方法,参数1:json结果,参数2:想要转哪一个类型
152 List<Plan> plans = gson.fromJson(jsonResult, type);
153
154 // 由于要使用GridView表示,绑定数据时只能使用Map<K,T>的类型,并且多个记录时,要用List<Map<K,T>>
155 // 先实例化
156 List<Map<String, String>> mPlans = new ArrayList<Map<String, String>>();
157 // 实例化一个title,是GridView的列头
158 Map<String, String> title = new HashMap<String, String>();
159 title.put("id", "序号");
160 title.put("pcb", "机种名");
161 title.put("amount", "计划数");
162 // 首先把表头追加到List<Map<String, String>>
163 mPlans.add(title);
164
165 // for循环从json转过来的List<Plan>
166 for (Plan plan : plans) {
167 // 实例化用于接收plan的HashMap<K,T>类
168 HashMap<String, String> hmPlans = new HashMap<String, String>();
169 // 使用put()方法把数值加入到HashMap<K,T>,参数1:键,参数2:值
170 hmPlans.put("id", plan.id);
171 hmPlans.put("pcb", plan.pcb);
172 hmPlans.put("amount", plan.amount);
173 // 把HashMap加入到List<Map>中
174 mPlans.add(hmPlans);
175 }
176
177 // SimpleAdapter是GridView的适配器,参数1:上下文内容,参数2:List<Map<K,T>>对象,参数3:GridView的布局文件,指每一个item的布局,需要在res/layout中创建xml,
178 // 参数4:String数组,指每一列要绑定到Map中的值,数组中的值就是上文“hmPlans.put("id",
179 // plan.id);”的键"id"
180 // 参数5:列头的显示文件,存放在res/values/strings.xml
181 SimpleAdapter sa = new SimpleAdapter(getApplicationContext(), mPlans, R.layout.planlist,
182 new String[] { "id", "pcb", "amount" }, new int[] { R.id.header1, R.id.header2, R.id.header3 });
183 // 把SimpleAdapter绑定到GridView
184 gv.setAdapter(sa);
185
186 // 气泡提示
187 Toast.makeText(getApplicationContext(), "读取成功!", Toast.LENGTH_SHORT).show();
188 break;
189 default:
190 Toast.makeText(getApplicationContext(), "操作失败!", Toast.LENGTH_SHORT).show();
191 break;
192 }
193 }
194 };
195
196 // 用于接收EditText的输入值,并赋值到字符串
197 public void GetMsg() {
198 id = etId.getText().toString().trim();
199 pcb = etPcb.getText().toString().trim();
200 amount = etAmount.getText().toString().trim();
201 }
202
203 // Insert()方法,通过判断受影响行数,返回“添加成功”或“操作失败”
204 public String Insert() {
205 String sql = "INSERT INTO [DayPlan]([ID],[PCBA],[AMOUNT]) VALUES (?,?,?)";
206 GetMsg();
207 List<Object> params = new ArrayList<Object>();
208 params.add(id);
209 params.add(pcb);
210 params.add(amount);
211 try {
212 int count = sh.ExecuteNonQuery(sql, params);
213 if (count == 1) {
214 return "添加成功!";
215 } else {
216 return "操作失败!";
217 }
218 } catch (Exception e) {
219 // TODO Auto-generated catch block
220 System.out.println(e.getMessage());
221 return "操作失败!";
222 }
223 }
224
225 public String Update() {
226 String sql = "UPDATE [DayPlan] SET [PCBA]=?,[AMOUNT]=? where [ID]=?";
227 GetMsg();
228 // params用于存放变量参数,即sql中的“?”
229 List<Object> params = new ArrayList<Object>();
230 params.add(pcb);
231 params.add(amount);
232 params.add(id);
233 try {
234 int count = sh.ExecuteNonQuery(sql, params);
235 if (count == 1) {
236 return "更新成功!";
237 } else {
238 return "操作失败!";
239 }
240 } catch (Exception e) {
241 // TODO: handle exception
242 System.out.println(e.getMessage());
243 return "操作失败!";
244 }
245 }
246
247 public String Delete() {
248 String sql = "DELETE FROM [DayPlan] where [ID]=?";
249 GetMsg();
250 List<Object> params = new ArrayList<Object>();
251 params.add(id);
252 try {
253 int count = sh.ExecuteNonQuery(sql, params);
254 if (count == 1) {
255 return "删除成功!";
256 } else {
257 return "操作失败!";
258 }
259 } catch (Exception e) {
260 // TODO: handle exception
261 System.out.println(e.getMessage());
262 return "操作失败!";
263 }
264 }
265
266 // Select()方法,查询生产计划
267 public String Select() {
268 String sql = "SELECT [ID] AS id,[PCBA] AS pcb,[AMOUNT] AS amount FROM [DayPlan] ORDER BY id";
269 String jsonResult = null;
270 try {
271 // sh.ExecuteQuery(),参数1:查询语句,参数2:查询用到的变量,用于本案例不需要参数,所以用空白的new
272 // ArrayList<Object>()
273 jsonResult = sh.ExecuteQuery(sql, new ArrayList<Object>());
274 } catch (Exception e) {
275 // TODO: handle exception
276 System.out.println(e.getMessage());
277 return null;
278 }
279 return jsonResult;
280 }
281
282 // 界面复位,清空显示
283 public void ClearEdit() {
284 //清空文本输入框
285 etId.setText("");
286 etPcb.setText("");
287 etAmount.setText("");
288 //etId获得焦点
289 etId.setFocusable(true);
290 etId.setFocusableInTouchMode(true);
291 etId.requestFocus();
292 etId.requestFocusFromTouch();
293 //清空GridView的绑定值
294 gv.setAdapter(null);
295 }
296
297 @Override
298 public boolean onCreateOptionsMenu(Menu menu) {
299 // Inflate the menu; this adds items to the action bar if it is present.
300 getMenuInflater().inflate(R.menu.main, menu);
301 return true;
302 }
303
304 @Override
305 public boolean onOptionsItemSelected(MenuItem item) {
306 // Handle action bar item clicks here. The action bar will
307 // automatically handle clicks on the Home/Up button, so long
308 // as you specify a parent activity in AndroidManifest.xml.
309 int id = item.getItemId();
310 if (id == R.id.action_settings) {
311 return true;
312 }
313 return super.onOptionsItemSelected(item);
314 }
315 }
完成。