資料持久化就是將記憶體中的資料模型轉換為儲存模型,以及將儲存模型轉換為記憶體中的資料模型的統稱。資料模型可以是任何資料結構或物件模型,儲存模型可以是關係模型、XML、二進位制流等。
儲存在記憶體的程式資料,程式退出,資料就消失了
儲存在磁碟上的程式資料,程式退出後依然存在
Hibernate、JPA、==JDBC(Java Datebase Connectivity)==等
java.sql.Driver 介面是所有 JDBC 驅動程式需要實現的介面。這個介面是提供給資料庫廠商使用的,不同資料庫廠商提供不同的實現
在程式中不需要直接去存取實現了 Driver 介面的類,而是由**驅動程式管理器類(java.sql.DriverManager)**去呼叫這些Driver實現
Connection conn = null;
Statement st=null;
ResultSet rs = null;
try {
//獲得Connection
//建立Statement
//處理查詢結果ResultSet
}catch(Exception e){
e.printStackTrance();
} finally {
//釋放資源ResultSet, Statement,Connection
}
1、在專案中建立lib資料夾
2、將jar檔案放置到lib資料夾
3、整合到專案中,右鍵build(eclipse)、add as library(idea)
將com.mysql.jdbc包下的Driver類的位元組碼檔案從本地磁碟載入到方法區中
==Oracle的驅動==:oracle.jdbc.driver.OracleDriver
==mySql的驅動==: com.mysql.jdbc.Driver
方式一:載入 JDBC 驅動需呼叫 Class 類的靜態方法 forName(),向其傳遞要載入的 JDBC 驅動的類名
//將com.mysql.jdbc包下的Driver類的位元組碼檔案從本地磁碟載入到方法區中
Class.forname("com.mysql.jdbc.Driver")
方式二:DriverManager 類是驅動程式管理器類,負責管理驅動程式
DriverManager.registerDriver(com.mysql.jdbc.Driver);
通常不用顯式呼叫 DriverManager 類的 registerDriver() 方法來註冊驅動程式類的範例,原因:
1、該方法,過於依賴jar包的存在
2、該方法,會造成二次註冊
3、使用Class.forname可以降低耦合性
//本機IP:localhost 本機埠號:3306
String url = "jdbc:mysql://IP地址:埠號/庫名?serverTimezone=Asia/Shanghai&characterEncoding=utf-8";
String user = "使用者名稱";
String passWord = "密碼";
Connection conn = DriverManager.getConnection(url,user,passWord);
協定:JDBC URL中的協定總是jdbc
子協定:子協定用於標識一個資料庫驅動程式
子名稱:一種標識資料庫的方法。子名稱可以依不同的子協定而變化,用子名稱的目的是為 了定位資料庫提供足夠的資訊。包含主機名(對應伺服器端的ip地址),埠號,資料庫名
對於 Oracle 資料庫連線,採用如下形式:
jdbc:oracle:thin:@localhost:1521:庫名
對於 SQLServer 資料庫連線,採用如下形式:
jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=庫名
對於 MYSQL 資料庫連線,採用如下形式:
jdbc:mysql://localhost:3306/庫名
Statement statement = conn.createStatement();
int result = statement.executeUpdate("sql語句字串物件")
//使用Statement類的方法ResultSet executeQuery(String sql);獲得結果集型別的物件
ResultSet set = statement.executeQuery(sql);
while(set.next()){
//形參可以直接寫欄位名,欄位名不區分大小寫
String id = set.getInt("book_id");
//也可以寫欄位索引,索引從1開始
String id = set.getInt(1);
}
resultSet.close();
statement.close();
connection.close();
將獲取連線和關閉資源等公共、重複的程式碼封裝成一個工具類
import java.sql.*;
public class JDBCUtil {
private static String driver;
private static String url;
private static String user;
private static String passWord;
//解析組態檔.properties
static {
try {
Properties properties = new Properties();
properties.load(new FileInputStream(".properties檔案路徑"));
driver = (String) properties.get("driver");
url = (String) properties.get("url");
user = (String) properties.get("user");
passWord = (String) properties.get("passWord");
}catch (Exception e){
e.printStackTrace();
}
}
//獲得Connection物件
public static Connection getConnection(){
Connection connection = null;
try{
Class.forName(driver);
connection = DriverManager.getConnection(url,user,passWord);
}catch (Exception e){
e.printStackTrace();
}
return connection;
}
//關閉資源 -- 針對查詢
public static void close(ResultSet resultset,Statement statement,Connection connection){
try {
if (resultset != null) {
resultset.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
//關閉資源 -- 針對增刪改
public static void close(Statement statement,Connection connection){
close(null,statement,connection);
}
//針對DML語句--增刪改
public static boolean executeUpdate(String sql,List<Object> list){
Connection connection = getConnection();
PreparedStatement pre = null;
try {
pre = connection.prepareStatement(sql);
for (int i = 0;i < list.size();i++){
pre.setObject(i + 1,list.get(i));
}
return (pre.executeUpdate() > 0)? true : false;
}catch (Exception e){
e.printStackTrace();
}finally {
close(pre,connection);
}
return false;
}
//針對查DQL語句
public static <T> List<T> executeQuery(String sql,List<Object> list,Class<T> tClass){
Connection connection = getConnection();
PreparedStatement statement = null;
ResultSet resultSet = null;
List<T> li = new ArrayList<>();
try {
statement = connection.prepareStatement(sql);
for (int i = 0;i < list.size();i++){
statement.setObject(i + 1,list.get(i));
}
resultSet = statement.executeQuery();
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
//獲取列數
int count = resultSetMetaData.getColumnCount();
//遍歷所有行
while (resultSet.next()){
T t = tClass.newInstance();
for (int i = 1;i <= count;i++){
//獲取每一列列名
String keyName = resultSetMetaData.getColumnLabel(i);
//獲取每一列對應的值
Object value = resultSet.getObject(keyName);
//T中對應的屬性
Field key = tClass.getDeclaredField(keyName);
key.setAccessible(true);
key.set(t,value);
}
li.add(t);
}
}catch (Exception e){
e.printStackTrace();
}finally {
close(connection,statement,resultSet);
}
return li;
}
}
List<Map> list = JDBCUtils.executeQuery(sql,new ArrayList());
for (Map<String,Object> map : list){
for (Map.Entry<String,Object> entry : map.entrySet()){
String s = entry.getKey();
Object o = entry.getValue();
System.out.print(s + "=" + o + ",");
}
System.out.println();
}
SQL 注入是利用某些系統沒有對使用者輸入的資料進行充分的檢查,而在 使用者輸入資料中注入非法的 SQL 語句段或命令,如下,從而利用系統的 SQL 引擎完成惡意行為的做法。
SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1'
對於 Java 而言,要防範 SQL 注入,只要用 PreparedStatement(繼承於Statement) 取代 Statement 就可以了
1、可以通過呼叫 Connection 物件的 preparedStatement() 方法獲取 PreparedStatement 物件
2、PreparedStatement 介面是 Statement 的子介面,它表示一條預編譯過的 SQL 語句
1、程式碼的可讀性和可維護性
2、PreparedStatement 能最大可能提高效能
3、PreparedStatement 可以防止 SQL 注入
4、如果拼接表名、列名、關鍵字,必須使用Statement,防止sql語句錯誤
1、通過呼叫 PreparedStatement 物件的 excuteQuery() 方法建立該物件
2、代表結果集
3、ResultSet 返回的實際上就是一張資料表.,有一個指標指向資料表的第一條記錄的前面。
1、通過呼叫ResultSet物件的getMetaData()方法建立改物件
2、可用於獲取關於 ResultSet 物件中列的型別和屬性資訊的物件
**DAO (Data Access objects 資料存取物件)**是指位於業務邏輯和持久化資料之間實現對持久化資料的存取。通俗來講,就是將資料庫操作都封裝起來。能夠是程式碼的結構更加清晰化。