jdbc連線Mysql
一:JDBC連線
在IJ中使用maven構建一個專案,在pom.xml中加入依賴:
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> <scope>runtime</scope> </dependency> </dependencies>
使用JDBC時,Connection代表一個JDBC連線,它相當於Java程式到資料庫的連線(通常是TCP連線)。開啟一個Connection時,需要準備URL、使用者名稱和口令,才能成功連線到資料庫。
URL是由資料庫廠商指定的格式,Mysql的URL是:
jdbc:mysql://<hostname>:<port>/<db>?key1=value1&key2=value2
我的Mysql執行在本地localhost
,通過SHOW DATABASES
和STATUS
分別確認了資料庫的名稱和埠號(port),故URL為:
jdbc:mysql://localhost:3306/crashcourse?useSSL=false&characterEncoding=utf8
其中useSSL=false
表示不使用SSL加密,characterEncoding=utf8
表示使用UTF-8作為字元編碼。
連線資料庫程式碼:
// JDBC連線的URL, 不同資料庫有不同的格式: String JDBC_URL = "jdbc:mysql://localhost:3306/test"; String JDBC_USER = "root"; String JDBC_PASSWORD = "password"; // 獲取連線: Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD); // TODO: 訪問資料庫... // 關閉連線: conn.close();
二:JDBC查詢
獲取到JDBC連線後,下一步我們就可以查詢資料庫了。查詢資料庫分以下幾步:
第一步,通過Connection
提供的prepareStatement()
方法建立一個PreparedStatement
物件,用於執行一個查詢;
第二步,執行PreparedStatement
物件提供的executeQuery("SELECT * FROM <db>")
並傳入SQL語句,執行查詢並獲得返回的結果集,使用ResultSet
來引用這個結果集;
第三步,反覆呼叫ResultSet
的next()
方法並讀取每一行結果。
為什麼使用PreparedStatement而不使用Statement
:
使用Statement拼字串非常容易引發SQL注入的問題,使用PreparedStatement可以完全避免SQL注入的問題。
使用Java對資料庫進行操作時,必須使用PreparedStatement,嚴禁任何通過引數拼字串的程式碼!PreparedStatement始終使用?
作為佔位符,然後通過setObject(索引,值)
設定每個佔位符?
的值(索引從1開始)。(當然還可以用setString,setBoolean)
為什麼要用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢:
問題就在於List介面有多個實現類,現在你用的是ArrayList,也許哪一天你需要換成其它的實現類,如 LinkedList或者Vector等等,這時你只要改變這一行就行了。
JDBC查詢的返回值總是ResultSet
:
**結果集(ResultSet)**是資料中查詢結果返回的一種物件,可以說結果集是一個儲存查詢結果的物件,但是結果集並不僅僅具有儲存的功能,他同時還具有操縱資料的功能,可能完成對資料的更新等. 。結果集讀取資料的方法主要是getXXX(),他的引數可以是整型表示第幾列(是從1開始的,而不是0),還可以是列名,使用String
型別的列名比索引要易讀,而且不易出錯。返回的是對應的XXX型別的值。如果對應那列是空值,XXX是物件的話返回XXX型的空值,如果XXX是數字型別,如Float等則返回0,boolean返回false.使用getString()可以返回所有的列的值,不過返回的都是字串型別的。XXX可以代表的型別有: 基本的資料型別如整型(int),布林型(Boolean),浮點型(Float,Double)等,位元型(byte),還包括一些特殊的型別,如:日 期型別(java.sql.Date),時間型別(java.sql.Time),時間戳型別(java.sql.Timestamp),大數型 (BigDecimal和BigInteger等)等。還可以使用getArray(intcolindex/String columnname),通過這個方法獲得當前行中,colindex所在列的元素組成的物件的陣列。使用getAsciiStream(intcolindex/String colname)可以獲得該列對應的當前行的ascii流。也就是說所有的getXXX方法都是對當前行進行操作。 結果集從其使用的特點上 可以分為四類,這四類的結果集的所具備的特點都是和Statement語句的建立有關,因為結果集是通過Statement語句執行後產生的,所以可以 說,結果集具備何種特點,完全決定於Statement。
//示例:查詢了執行在我電腦本地的Mysql中的資料庫(<db>)crashcourse中的表(TABLE)中的所有行和列
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args){
try {
List<customers> customers = queryCustomers(); //查詢
customers.forEach(System.out::println);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
static List<customers> querycustomers() throws SQLException{
List<customers> customers = new ArrayList<customers>();
try(Connection conn = DriverManager.getConnection(jdbcUrl,jdbcUsername,jdbcPassword)){ //連線資料庫
try(PreparedStatement ps = conn.prepareStatement("SELECT * FROM customers")){ //傳入SQL語句
try(ResultSet rs = ps.executeQuery()){ //執行查詢命令獲得返回的結果集,並使用ResultSet來引用這個結果集
while (rs.next()){
customers.add(extractRow(rs)); //將所有結果存入customers中
}
}
}
}
return customers;
}
static customers extractRow(ResultSet rs) throws SQLException{
customers std = new customers();
std.setCust_id(rs.getInt("cust_id"));
std.setCust_name(rs.getString("cust_name"));
std.setCust_address(rs.getString("cust_address"));
std.setCust_city(rs.getString("cust_city"));
std.setCust_state(rs.getString("cust_state"));
std.setCust_zip(rs.getInt("cust_zip"));
std.setCust_country(rs.getString("cust_country"));
std.setCust_contact(rs.getString("cust_contact"));
std.setCust_email(rs.getString("cust_email"));
return std;
}
static final String jdbcUrl = "jdbc:mysql://localhost:3306/crashcourse?useSSL=false&characterEncoding=utf8";
static final String jdbcUsername = "root";
static final String jdbcPassword = "***";
}
//構建的customers類
public class customers {
private int cust_id;
private String cust_name;
private String cust_address;
private String cust_city;
private String cust_state;
private int cust_zip;
private String cust_country;
private String cust_contact;
private String cust_email;
public int getCust_id() {
return cust_id;
}
public void setCust_id(int cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_address() {
return cust_address;
}
public void setCust_address(String cust_address) {
this.cust_address = cust_address;
}
public String getCust_city() {
return cust_city;
}
public void setCust_city(String cust_city) {
this.cust_city = cust_city;
}
public String getCust_state() {
return cust_state;
}
public void setCust_state(String cust_state) {
this.cust_state = cust_state;
}
public int getCust_zip() {
return cust_zip;
}
public void setCust_zip(int cust_zip) {
this.cust_zip = cust_zip;
}
public String getCust_country() {
return cust_country;
}
public void setCust_country(String cust_country) {
this.cust_country = cust_country;
}
public String getCust_contact() {
return cust_contact;
}
public void setCust_contact(String cust_contact) {
this.cust_contact = cust_contact;
}
public String getCust_email() {
return cust_email;
}
public void setCust_email(String cust_email) {
this.cust_email = cust_email;
}
@Override
public String toString() {
return "customers{" +
"cust_id=" + cust_id +
", cust_name='" + cust_name + '\'' +
", cust_address='" + cust_address + '\'' +
", cust_city='" + cust_city + '\'' +
", cust_state='" + cust_state + '\'' +
", cust_zip=" + cust_zip +
", cust_country='" + cust_country + '\'' +
", cust_contact='" + cust_contact + '\'' +
", cust_email='" + cust_email + '\'' +
'}';
}
}
三:JDBC增、刪、改
增刪改查除了用PreparedStatement
分別執行對應的SQL語句和最後執行的是executeUpdate()
而不是executeQuery
,其他程式碼與
查詢時基本一致。
//插入操作(增)
static void insertCustomers(String cust_name,String cust_address,String cust_city,String cust_state,int cust_zip,String cust_country,String cust_contact,String cust_email) throws SQLException {
try(Connection conn = DriverManager.getConnection(jdbcUrl,jdbcUsername,jdbcPassword)){ //連線資料庫
try (PreparedStatement ps = conn.prepareStatement("INSERT INTO customers(cust_name,cust_address,cust_city,cust_state, cust_zip,cust_country,cust_contact,cust_email) VALUES (?,?,?,?,?,?,?,?)")){
ps.setObject(1, cust_name);
ps.setObject(2, cust_address);
ps.setObject(3, cust_city);
ps.setObject(4, cust_state);
ps.setObject(5, cust_zip);
ps.setObject(6, cust_country);
ps.setObject(7, cust_contact);
ps.setObject(8, cust_email);
ps.executeUpdate();
}
}
}
//刪
static void deleteCustomers(int cust_id) throws SQLException {
try(Connection conn = DriverManager.getConnection(jdbcUrl,jdbcUsername,jdbcPassword)){
try(PreparedStatement ps = conn.prepareStatement("DELETE FROM customers WHERE cust_id=?")){
ps.setObject(1,cust_id);
ps.executeUpdate();
}
}
}
//改(更新)(此處以更新cust_id=10006的cust_name列為updataTest為例示範)
static void updateCustomers() throws SQLException {
try (Connection conn = DriverManager.getConnection(jdbcUrl,jdbcUsername,jdbcPassword)){
try(PreparedStatement ps = conn.prepareStatement("UPDATE customers SET ?=? WHERE cust_id=?")){
ps.setObject(1,"cust_name");
ps.setObject(1,"updataTest");
ps.setObject(2,10006);
ps.executeUpdate();
} }
}