## Java操作數據庫--以SQL?Server為例
### crud介紹(增、刪、改、查操作)
CRUD是指在做計算處理時的增加(Create)、查詢(Retrieve)(重新得到數據)、更新(Update)和刪除(Delete)幾個單記事的首字母簡寫。主要被用在描述軟件系統中數據庫或者持久層的基本操作功能。
?
### crud介紹
要對數據表進行增、刪、改、查,首先要清楚jdbc基本的概念:


? ? JDBC有兩種,一種原sun公司提供的數據庫連接api但不是直接連接sql?server而是先連接ODBC再通過ODBC對sql?server進行操作;一種是由微軟提供的JDBC數據庫連接api可直接對sql?server數據庫進行操作。
????JDBC(Java?Data?Base?Connectivity,java數據庫連接)是一種用于執行SQL語句的Java?API,可以為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC提供了一種基準,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序,同時,JDBC也是個商標名。
????有了JDBC,向各種關系數據發送SQL語句就是一件很容易的事。換言之,有了JDBC?API,就不必為訪問Sybase數據庫專門寫一個程序,為訪問Oracle數據庫又專門寫一個程序,或為訪問Informix數據庫又編寫另一個程序等等,程序員只需用JDBC?API寫一個程序就夠了,它可向相應數據庫發送SQL調用。同時,將Java語言和JDBC結合起來使程序員不必為不同的平臺編寫不同的應用程序,只須寫一遍程序就可以讓它在任何平臺上運行,這也是Java語言“編寫一次,處處運行”的優勢。
注:JDBC訪問不同的數據庫使用的JDBC?API都有所不同,雖然統稱為JDBC。如:訪問sql?server數據庫的JDBC,是不能訪問oracle數據庫的,同理也是也不訪問mysql、db2、Informix數據庫等。只是訪問方式不同,對數據庫的操作依然是使用sql語句操作。
?
?
### jdbc的驅動的分類
目前比較常見的JDBC驅動程序可分為以下四個種類
1、jdbc-odbc橋連接
2、本地協議純java驅動程序
3、網絡協議純java驅動程序
4、本地api
?
### jdbc不足
盡管JDBC在JAVA語言層面實現了統一,但不同數據庫仍舊有許多差異。為了更好地實現跨數據庫操作,于是誕生了Hibernate項目,Hibernate是對JDBC的再封裝,實現了對數據庫操作更寬泛的統一和更好的可移植性。
?
?
### jdbc-odbc橋連的方式來操作sql?server數據庫
**PS:SQL文件可以到我寫的上一篇博客“Java數據庫基礎”中找到。**
~~~
/**
* 使用JDBC-ODBC橋連方式操作數據庫 db中的emp,dept表
* 1.配置數據源
* 2.在程序中連接數據源
*/
package com.db;
import java.sql.*;
public class db1 {
public static void main(String[] args) {
Connection ct = null;
Statement sm = null;
ResultSet rs = null;
try {
//1.加載驅動(把需要的驅動程序加入內存)
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//2.得到連接(指定連接哪個數據源,用戶和密碼)
//配置數據源時,選擇Windows NT驗證,則不需要賬號密碼
ct = DriverManager.getConnection("jdbc:odbc:mytest");
//3.創建Statement或者PreparedStatement
//Statement用處是:發送sql語句到數據庫
sm = ct.createStatement();
//4.執行(crud,創建數據庫,備份數據庫,刪除數據庫。。。)
//添加一條數據到dept表
//executeUpdate可以執行 cud操作(添加,刪除,修改)
// String sql = "insert into dept values(50, '保安部', '北京')";
// int res = sm.executeUpdate(sql);
// if(res == 1){
// System.out.println("加入一條語句");
// } else {
// System.out.println("添加失敗");
// }
//從dept刪除一條記錄
// String sql = "delete from dept where deptno='50'";
// int res = sm.executeUpdate(sql);
//
// if(res == 1){
// System.out.println("delete.");
// } else {
// System.out.println("failure");
// }
//修改deptno=40的loc改為beijing
// String sql = "update dept set loc = 'beijing' where deptno='40'";
// int res = sm.executeUpdate(sql);
// if(res == 1){
// System.out.println("update.");
// } else {
// System.out.println("failure");
// }
//顯示所有的部門
//ResultSet結果集
String sql = "select * from dept";
rs = sm.executeQuery(sql);
//rs指向結果集的第一行的前一行
while(rs.next()){
//取出第一行
int deptno = rs.getInt(1);
String dname = rs.getString(2);
String loc = rs.getString(3);
System.out.println(deptno + " " + dname + " " + loc);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//關閉資源
//誰后創建,誰先關閉
try {
if(rs != null){
rs.close();
}
if(sm != null){
sm.close();
}
if(ct != null){
ct.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
~~~
?
?
### Statement和PreparedStatement的區別(1)
????Statemen和PreparedStatement都可以用于把sql語句從java程序中發送到指定數據庫,并執行sql語句,但是他們也存在區別:
1、直接使用Statement,驅動程序一般不會對sql語句作處理而直接交給數據庫;使用PreparedStatement,形成預編譯的過程,并且會對語句作字符集的轉換(至少在sql?server)中如此。
????如此,有兩個好處:對于多次重復執行的語句,使用PreparedStament效率會更高一點,并且在這種情況下也比較適合使用batch;另外,可以比較好地解決系統的本地化問題。
2、PreparedStatement還能有效的防止危險字符的注入,也就是sql注入的問題。
?
### Statement和PreparedStatement的區別(2)
看下面兩段程序片斷:
Code?Fragment?1:
~~~
String updateString="UPDATE COFFEES SET SALES=75"+"WHERE COF_NAME LIKE 'Colombian'";
stmt.executeUpdate(updateString);
~~~
Code?Fragment?2:
~~~
PreparedStatement updateSales=con.prepareStatement("UPDATE COFFEES SET SALES=? WHERE COF_NAME LIKE ?");
updateSales.setInt(1,75);
updateSales.setString(2,"Colombian");
updateSales.executeUpdate();
~~~
????后者使用了PreparedStatement,而前者是Statement,PreparedStatement不僅包含了SQL語句,而且大多數情況下這個語句已被預編譯過,當其執行時,只需DBMS運行SQL語句,而不必先編譯。當你需要執行Statement對象多次的時候,PreparedStatement對象將會降低運行時間,加快了訪問數據庫的速度。
????好處是,不必重復SQL語句的句法,而只需要改其中變量的值,便可重新執行SQL語句。選擇PreparedStatement對象與否,在于相同句法的SQL語句是否執行了多次,而且兩次之間的差別僅是變量的不同。如僅執行一次的話,它和普通的對象無差異,體現不出預編譯的優越性。
~~~
/**
* PreparedStatement使用CRUD
* 1.PreparedStatement 可以提高執行效率(因為有預編譯功能)
* 2.PreparedStatement 可以防止sql注入,但是要用?賦值的方式
*/
package com.db;
import java.sql.*;
public class db2 {
public static void main(String[] args) {
//定義對象
PreparedStatement ps = null;
Connection ct = null;
ResultSet rs = null;
try {
//加載驅動
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//得到連接
ct = DriverManager.getConnection("jdbc:odbc:mytest");
// //查詢
// //創建PreparedStatement
// ps = ct.prepareStatement("select * from dept where deptno=? and loc=?");
// //設置參數
// ps.setInt(1, 20);
// ps.setString(2, "dallas");
// //執行查詢
// rs = ps.executeQuery();
//
// while(rs.next()){
// System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getString(3));
// }
//插入
//創建PreparedStatement
ps = ct.prepareStatement("insert into dept values(?,?,?)");
//設置參數
ps.setInt(1, 50);
ps.setString(2, "deploy");
ps.setString(3, "beijing");
//執行插入
int res = ps.executeUpdate();
if(res == 1){
System.out.println("insert.");
} else {
System.out.println("failure.");
}
} catch (Exception e) {
e.printStackTrace();
} finally{
//關閉資源
try{
if(rs != null){
rs.close();
}
if(ct != null){
ct.close();
}
if(ps != null){
ps.close();
}
}catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
~~~
### JDBC-ODBC橋連操作sql?server與JDBC驅動直連操作sql?server的區別:
1、JDBC-ODBC橋連sql?server無需引入外部驅動
2、JDBC直連需要引入微軟提供的JDBC驅動
~~~
/**
* jdbc方式操縱數據庫
* 1.引入java.sql.*;
* 2.引入jar包
* 3.sqlserver2000需要引入三個jar包,分別是msbase.jar和mssqlserver.jar和msutil.jar
* 4.sqlserver2005/2008/2012版本中可以引入sqljdbc.jar或sqljdbc4.jar兩個微軟提供的JDBC包,官方目前推出2.0/3.0/4.0版本
* 5.使用sqljdbc4.jar后可以不使用加載驅動Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");而直接連接數據庫
* 6.使用sqljdbc.jar則需要加載驅動
* 7.特別說明,如果取值是按編號取,則需一一對應;如果按字段列名取值,則可以靈活取值
*/
package com.db;
import java.sql.*;
public class db3 {
public static void main(String[] args) {
// 定義
Connection ct = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 初始化對象
// 1.加載驅動
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// 2.得到連接
ct = DriverManager.getConnection(
"jdbc:sqlserver://127.0.0.1:1433; DatabaseName=db", "sa",
"123456");
// //3.創建PraparedStatement
// ps = ct.prepareStatement("select * from emp");
// //4.執行(如果是增刪改使用executeUpdate(),如果是查詢則使用executeQuery())
// rs = ps.executeQuery();
//
// //循環取出員工的名字,薪水,部門編號
// while(rs.next()){
// String ename = rs.getString("ename");
// float sal = rs.getFloat(6);
// int deptno = rs.getInt(8);
// System.out.println(ename + " " + sal + " " + deptno);
// }
// //3.創建PraparedStatement
// ps =
// ct.prepareStatement("select ename,sal,dname from emp,dept where emp.deptno = dept.deptno ");
// //4.執行(如果是增刪改使用executeUpdate(),如果是查詢則使用executeQuery())
// rs = ps.executeQuery();
//
// //循環取出員工的名字,薪水,部門名稱
// while(rs.next()){
// String ename = rs.getString("ename");
// float sal = rs.getFloat("sal");
// String deptName = rs.getString("dname");
// System.out.println(ename + " " + sal + " " + deptName);
// }
// 3.創建PraparedStatement
ps = ct.prepareStatement("insert into dept values(?,?,?)");
// 4.執行(如果是增刪改使用executeUpdate(),如果是查詢則使用executeQuery())
// 賦值
ps.setInt(1, 60);
ps.setString(2, "software");
ps.setString(3, "beijing");
int res = ps.executeUpdate();
if (res == 1) {
System.out.println("insert.");
} else {
System.out.println("failure.");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (ct != null) {
ct.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
~~~
### java程序中來控制對數據庫(表)的創建、刪除、備份、恢復工作
~~~
/**
* 在java中如何使用ddl語句(create,drop,backup...)
*/
package com.db;
import java.sql.*;
public class db4 {
public static void main(String[] args) {
Connection ct = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 初始化對象
// 1.加載驅動
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// 2.得到連接
ct = DriverManager.getConnection(
"jdbc:sqlserver://127.0.0.1:1433; DatabaseName=db", "sa",
"123456");
// 3.創建PrepareStatement
//創建數據庫
//ps = ct.prepareStatement("create database test");
//創建表
//ps = ct.prepareStatement("create table test2(tNo int)");
//備份數據庫
ps = ct.prepareStatement("backup database test to disk='C:/test.bak'");
// 執行ddl語句
boolean b = ps.execute();
if(!b){
System.out.println("ok");
}else{
System.out.println("failure");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 關閉連接
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (ct != null) {
ct.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
~~~
### 實例:學生管理系統
### JTable的使用
~~~
/**
* JTable的使用
*/
package com.db;
import javax.swing.*;
import java.util.*;
import java.sql.*;
import java.awt.*;
import java.awt.event.*;
public class db5 extends JFrame{
//rowData用來存放行數據
//columnNames存放列名
Vector rowData;
//columnNames存放列名
Vector columnNames;
//定義組件
JTable jt = null;
JScrollPane jsp = null;
//構造方法
public db5(){
columnNames = new Vector();
//設置列名
columnNames.add("學號");
columnNames.add("名字");
columnNames.add("性別");
columnNames.add("年齡");
columnNames.add("籍貫");
columnNames.add("系別");
rowData = new Vector();
//rowData存放多行
Vector row = new Vector();
row.add("001");
row.add("張三");
row.add("男");
row.add("20");
row.add("湖南");
row.add("軟件工程");
//加入到rowData
rowData.add(row);
//創建組件
jt = new JTable(rowData, columnNames);
jsp = new JScrollPane(jt);
//添加到JFrame
add(jsp);
//設置窗體
setTitle("JTable的使用");
setSize(400, 300);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
db5 gui1 = new db5();
}
}
~~~
### JTable顯示從數據庫讀取的學生信息
~~~
/**
* 從數據庫讀取學生信息
*/
package com.db;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.sql.*;
public class db6 extends JFrame {
// 定義數據庫資源
Connection ct = null;
PreparedStatement ps = null;
ResultSet rs = null;
// rowData用來存放行數據
// columnNames存放列名
Vector rowData;
// columnNames存放列名
Vector columnNames;
// 定義組件
JTable jt = null;
JScrollPane jsp = null;
// 構造方法
public db6() {
columnNames = new Vector();
// 設置列名
columnNames.add("學號");
columnNames.add("名字");
columnNames.add("性別");
columnNames.add("年齡");
columnNames.add("籍貫");
columnNames.add("系別");
rowData = new Vector();
// rowData存放多行
// 從數據庫取數據
try {
// 加載驅動
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// 獲取連接
ct = DriverManager.getConnection(
"jdbc:sqlserver://127.0.0.1:1433; DatabaseName=StuManage",
"sa", "123456");
// 創建PreparedStatement
ps = ct.prepareStatement("select * from stu");
// 執行查詢
rs = ps.executeQuery();
// 循環獲取數據
while (rs.next()) {
// rowData存放多行數據
// 定義一行數據
Vector row = new Vector();
row.add(rs.getInt("stuId"));
row.add(rs.getString("stuName"));
row.add(rs.getString("stuSex"));
row.add(rs.getInt("stuAge"));
row.add(rs.getString("stujg"));
row.add(rs.getString("stuDept"));
// 添加到rowData
rowData.add(row);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 關閉資源
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (ct != null) {
ct.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
// 創建組件
jt = new JTable(rowData, columnNames);
jsp = new JScrollPane(jt);
// 添加到JFrame
add(jsp);
// 設置窗體
setTitle("JTable的使用");
setSize(400, 300);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
db6 ui = new db6();
}
}
~~~
### Mini學生管理系統
~~~
--創建數據庫
create database StuManage;
--使用數據庫
use StuManage;
--創建學生表
create table stu
(
stuId int primary key identity(10000,1), --學號
stuName nvarchar(50) not null, --姓名
stuSex nchar(1) check(stuSex in('男','女')) default '男', --性別
stuAge int check(stuAge > 1), --年齡
stujg nvarchar(30), --籍貫
stuDept nvarchar(40) --專業
);
--插入數據
insert into stu values('張三','男',20,'湖南','軟件工程');
insert into stu values('李四','男',25,'湖北','通信工程');
insert into stu values('王五','男',15,'河北','制藥工程');
insert into stu values('趙麗','女',21,'湖南','英語');
--查詢
select * from stu;
~~~

#### Model1模式
源碼:[https://code.csdn.net/snippets/1367849](https://code.csdn.net/snippets/1367849)

#### Model2模式
源碼:[https://code.csdn.net/snippets/1367938](https://code.csdn.net/snippets/1367938)

#### Model2模式改進
源碼:[https://code.csdn.net/snippets/1367979](https://code.csdn.net/snippets/1367979)
----------參考《韓順平.循序漸進學.java.從入門到精通》
----------參考《JDK_API_1_6_zh_CN》
Java學習筆記--導航[http://blog.csdn.net/q547550831/article/details/49819641](http://blog.csdn.net/q547550831/article/details/49819641)