使用JDBC構建簡單的資料訪問層
本文由碼農網 – 段生原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃!
以下是如何使用JDBC構建一個資料訪問層,包括資料轉換(將從資料庫中查詢的資料封裝到對應的物件中……),資料庫的建立,以及如何連線到資料庫。
本教程的目的是使用Java編寫的分離的層去訪問資料庫中的表,這一層通常稱為資料訪問層(DAL)
使用DAL的最大好處是通過直接使用一些類似insert()和find()的方法簡化了資料庫的訪問操作,而不是總是先做連結,再執行一些查詢。
該層在其內部處理所有與資料庫相關的呼叫和查詢。
建立資料庫
我們希望為使用者創造一個簡單的表,我們可以使用這些欄位來建立
id int name varchar(200) password varchar(200) age int
資料傳輸物件
這一層應該包含一個簡單的類叫做資料傳輸物件(DTO)。這個類僅僅是一個與資料庫中的表相對應的簡單對映,表中的每一列對應類的一個成員變數。
我們的目的是使用簡單的Java物件,而不是處理SQL語句和其他與資料庫相關的命令來進行資料庫的增刪改查。
我們想要把表對映成java程式碼,只需要建立包含相同欄位的類(bean)即可
為了更好地封裝,除了建構函式我們應該宣告所有欄位變數為私有,創造訪問器(getter和setter),其中有一個是預設的建構函式。
public class User { private Integer id; private String name; private String pass; private Integer age; }
為了正確地對映欄位,我們應該考慮資料庫中的NULL值。對於Java的原始的預設值,例如int型別,其預設值是0,所以我們應該提供可容納空值的新的資料型別。我們可以通過使用特殊的型別——封裝類,如Integer來代替 INT。
最後我們的類應該像這樣:
public class User { private Integer id; private String name; private String pass; private Integer age; public User() { } public User(String name, String pass, Integer age) { this.name = name; this.pass = pass; this.age = age; } public User(Integer id, String name, String pass, Integer age) { this.id = id; this.name = name; this.pass = pass; this.age = age; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } }
一個好的做法是,提供預設的空建構函式,一個完整的建構函式和一個沒有id引數的完整建構函式。
連線資料庫
我們可以使用一箇中間類來方便連線到資料庫,在這個類中,我們將提供資料庫的連線引數如資料庫JDBC, URL,使用者名稱和密碼,並將這些變數定義成final的(從properties 或者 xml配置檔案中獲取這些資料將會更好)
提供一個方法返回一個Connection物件或者當連線失敗時返回一個null又或者丟擲一個執行時異常。
public static final String URL = "jdbc:mysql://localhost:3306/testdb"; public static final String USER = "testuser"; public static final String PASS = "testpass"; /** * 獲取connection物件 * @return Connection 物件 */ public static Connection getConnection() { try { DriverManager.registerDriver(new Driver()); return DriverManager.getConnection(URL, USER, PASS); } catch (SQLException ex) { throw new RuntimeException("Error connecting to the database", ex); } }
我們也可以在類中包含一個主方法來測試連線。完整的類像這樣:
import com.mysql.jdbc.Driver; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * Connect to Database * @author hany.said */ public class ConnectionFactory { public static final String URL = "jdbc:mysql://localhost:3306/testdb"; public static final String USER = "testuser"; public static final String PASS = "testpass"; /** * Get a connection to database * @return Connection object */ public static Connection getConnection() { try { DriverManager.registerDriver(new Driver()); return DriverManager.getConnection(URL, USER, PASS); } catch (SQLException ex) { throw new RuntimeException("Error connecting to the database", ex); } } /** * Test Connection */ public static void main(String[] args) { Connection connection = connectionFactory.getConnection(); } }
資料訪問物件
DAO層可以做CRUD操作。它可以對我們的表進行增刪改查。
我們的DAO層介面應該像這樣:
public interface UserDao { User getUser(); Set<User> getAllUsers(); User getUserByUserNameAndPassword(); boolean insertUser(); boolean updateUser(); boolean deleteUser(); }
查詢使用者
使用者可以通過像ID,姓名或郵箱等任何唯一欄位來查詢。在這個例子中,我們使用ID來查詢使用者。第一步是通過聯結器類來建立一個connection,然後執行SELECT語句以獲得其ID為7的使用者,我們可以使用這條語句查詢使用者:
SELECT * FROM user WHERE id=7
就在這裡,我們做了一個動態的語句來從引數中獲取ID。
通過執行這個查詢,得到一個結果集,其中儲存有使用者或null。我們可以通過Resultset的next()方法來檢測是否有值。如果返回true,我們將繼續利用data getters從ResultSet中獲取使用者資料。當我們將所有的資料封裝到user中後,我們返回它。如果不存在此ID的使用者或其他任何異常發生(如無效的SQL語句)這個方法會返回null。
public User getUser(int id) { Connection connection = connectionFactory.getConnection(); try { Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM user WHERE id=" + id); if(rs.next()) { User user = new User(); user.setId( rs.getInt("id") ); user.setName( rs.getString("name") ); user.setPass( rs.getString("pass") ); user.setAge( rs.getInt("age") ); return user; } } catch (SQLException ex) { ex.printStackTrace(); } return null; }
使用單獨的方法來從結果集中提取資料將會更方便,因為在很多方法中我們將會呼叫它。
這個新方法將丟擲SQLException並且為了限制只能在類內部使用,其應該是私有的:
private User extractUserFromResultSet(ResultSet rs) throws SQLException { User user = new User(); user.setId( rs.getInt("id") ); user.setName( rs.getString("name") ); user.setPass( rs.getString("pass") ); user.setAge( rs.getInt("age") ); return user; }
我們上面的方法應該修改成新的方法:
public User getUser(int id) { Connection connection = connectionFactory.getConnection(); try { Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM user WHERE id=" + id); if(rs.next()) { return extractUserFromResultSet(rs); } } catch (SQLException ex) { ex.printStackTrace(); } return null; }
登陸方法
登陸操作類似。我們希望提供使用者和密碼替代ID,這將不會影響引數列表和查詢語句。如果使用者名稱和密碼是正確的,這個方法會返回一個有效的使用者,否則為null。因為有很多的引數,使用PreparedStatement將更有用。
public User getUserByUserNameAndPassword(String user, String pass) { Connector connector = new Connector(); Connection connection = connector.getConnection(); try { PreparedStatement ps = connection.prepareStatement("SELECT * FROM user WHERE user=? AND pass=?"); ps.setString(1, user); ps.setString(2, pass); ResultSet rs = ps.executeQuery(); if(rs.next()) { return extractUserFromResultSet(rs); } } catch (SQLException ex) { ex.printStackTrace(); } return null; }
查詢所有使用者的方法
這個方法將會返回所有的使用者,所以我們應該將它們存在一個類似陣列的容器中返回來。但是,因為我們不知道有多少條記錄。 使用例如Set或者List的集合將會更好:
public Set getAllUsers() { Connector connector = new Connector(); Connection connection = connector.getConnection(); try { Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM user"); Set users = new HashSet(); while(rs.next()) { User user = extractUserFromResultSet(rs); users.add(user); } return users; } catch (SQLException ex) { ex.printStackTrace(); } return null; }
插入方法
Insert方法將採取使用者作為引數,並使用PreparedStatement物件來執行SQL update語句。executeUpdate 方法返回受影響的行數。如果我們新增單行,意味著該方法應該返回1,如果是這樣,我們返回true,否則,我們返回false
public boolean insertUser(User user) { Connector connector = new Connector(); Connection connection = connector.getConnection(); try { PreparedStatement ps = connection.prepareStatement("INSERT INTO user VALUES (NULL, ?, ?, ?)"); ps.setString(1, user.getName()); ps.setString(2, user.getPass()); ps.setInt(3, user.getAge()); int i = ps.executeUpdate(); if(i == 1) { return true; } } catch (SQLException ex) { ex.printStackTrace(); } return false; }
更新方法
更新方法和插入方法類似。唯一變化的是SQL語句
public boolean updateUser(User user) { Connector connector = new Connector(); Connection connection = connector.getConnection(); try { PreparedStatement ps = connection.prepareStatement("UPDATE user SET name=?, pass=?, age=? WHERE id=?"); ps.setString(1, user.getName()); ps.setString(2, user.getPass()); ps.setInt(3, user.getAge()); ps.setInt(4, user.getId()); int i = ps.executeUpdate(); if(i == 1) { return true; } } catch (SQLException ex) { ex.printStackTrace(); } return false; }
刪除方法
刪除的方法是使用一個簡單的查詢像
DELETE FROM user WHERE ID = 7
帶上id引數傳送該查詢將刪除此記錄。如果成功刪除將返回1
public boolean deleteUser(int id) { Connector connector = new Connector(); Connection connection = connector.getConnection(); try { Statement stmt = connection.createStatement(); int i = stmt.executeUpdate("DELETE FROM user WHERE id=" + id); if(i == 1) { return true; } } catch (SQLException ex) { ex.printStackTrace(); } return false; }
譯文連結:http://www.codeceo.com/article/jdbc-dal.html
英文原文:Building Simple Data Access Layer Using JDBC
翻譯作者:碼農網 – 段生
[ 轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]
相關文章
- JDBC資料庫訪問JDBC資料庫
- Spring Boot入門(五):使用JDBC訪問MySql資料庫Spring BootJDBCMySql資料庫
- JDBC第一篇【介紹JDBC、使用JDBC連線資料庫、簡單的工具類】JDBC資料庫
- 使用 @NoRepositoryBean 簡化資料庫訪問Bean資料庫
- JDBC用ResultSet訪問大量資料時會遇到的問題JDBC
- 極簡架構模式-資料訪問物件模式架構模式物件
- jdbc訪問KingbaseES資料庫SocketTimeoutException Read timed outJDBC資料庫Exception
- spring mvc 的jpa JpaRepository資料層訪問SpringMVC
- 如何使用RedisTemplate訪問Redis資料結構Redis資料結構
- JDBC入門與簡單使用JDBC
- 利用angular4和nodejs-express構建一個簡單的網站(二)——設定跨域訪問和安裝基本依賴構建資料庫AngularNodeJSExpress網站跨域資料庫
- 使用 Python 構建一個簡單的 RESTful APIPythonRESTAPI
- orbeon form 的架構簡介 - 如何訪問使用者通過 form 儲存的資料ORBORM架構
- Redis系列(一)底層資料結構之簡單動態字串Redis資料結構字串
- 【直播預約】如何構建簡單高效的現代化資料棧
- webpack簡單搭建localhost訪問靜態資源Weblocalhost
- 資料結構簡單題資料結構
- (精華)2020年8月22日 ABP vNext 領域層和資料訪問層的單元測試
- java實現簡單的JDBCJavaJDBC
- 異構資料來源同步之表結構同步 → 透過 jdbc 實現,沒那麼簡單JDBC
- SpringBoot資料訪問之Druid資料來源的使用Spring BootUI
- ClownFish:比寫程式碼還快的通用資料訪問層
- 簡單介紹如何使用Bazel構建Golang程式Golang
- Hive學習之JDBC訪問HiveJDBC
- 構建最簡單陣列陣列
- spring 簡單的使用 Hikari連線池 和 jdbc連線mysql 的一個簡單例子SpringJDBCMySql單例
- jmeter 使用 ssh 方式訪問資料庫JMeter資料庫
- jdbc就是這麼簡單JDBC
- MongoDB最簡單的入門教程之二 使用nodejs訪問MongoDBMongoDBNodeJS
- 構建自己的簡單微服務架構(開源)微服務架構
- jdbc.utils QueryRunner的建檔使用JDBC
- [譯] 使用 Node 和 OAuth 2.0 構建一個簡單的 REST APIOAuthRESTAPI
- [譯] 如何使用原生 JavaScript 構建簡單的 Chrome 擴充套件程式JavaScriptChrome套件
- 利用BT構建簡單的CDN網路
- 用 Java 構建簡單的規則引擎Java
- ABP框架之——資料訪問基礎架構框架架構
- MySQL資料庫的基本使用簡單易懂MySql資料庫
- SpringBoot資料訪問之Druid啟動器的使用Spring BootUI
- 使用React構建簡單專案步驟(Mac 環境)ReactMac