本文主要补充介绍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 }
完成。