使用JDBC构建简单的数据访问层
本教程的目的是使用Java编写的分离的层去访问数据库中的表,这一层通常称为数据访问层(DAL)
使用DAL的最大好处是通过直接使用一些类似insert()和find()的方法简化了数据库的访问操作,而不是总是先做链接,再执行一些查询。
该层在其内部处理所有与数据库相关的调用和查询。
创建数据库
我们希望为用户创造一个简单的表,我们可以使用这些字段来创建
<code class="html">id int name varchar(200) password varchar(200) age int</code>
数据传输对象
这一层应该包含一个简单的类叫做数据传输对象(DTO)。这个类仅仅是一个与数据库中的表相对应的简单映射,表中的每一列对应类的一个成员变量。
我们的目的是使用简单的Java对象,而不是处理SQL语句和其他与数据库相关的命令来进行数据库的增删改查。
我们想要把表映射成java代码,只需要创建包含相同字段的类(bean)即可
为了更好地封装,除了构造函数我们应该声明所有字段变量为私有,创造访问器(getter和setter),其中有一个是默认的构造函数。
<code class="java">public class User { private Integer id; private String name; private String pass; private Integer age; }</code>
为了正确地映射字段,我们应该考虑数据库中的NULL值。对于Java的原始的默认值,例如int类型,其默认值是0,所以我们应该提供可容纳空值的新的数据类型。我们可以通过使用特殊的类型——封装类,如Integer来代替 INT。
最后我们的类应该像这样:
<code class="java">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; } }</code>
一个好的做法是,提供默认的空构造函数,一个完整的构造函数和一个没有id参数的完整构造函数。
连接数据库
我们可以使用一个中间类来方便连接到数据库,在这个类中,我们将提供数据库的连接参数如数据库JDBC, URL,用户名和密码,并将这些变量定义成final的(从properties 或者 xml配置文件中获取这些数据将会更好)
提供一个方法返回一个Connection对象或者当连接失败时返回一个null又或者抛出一个运行时异常。
<code class="java">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); } }</code>
我们也可以在类中包含一个主方法来测试连接。完整的类像这样:
<code class="java">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(); } }</code>
数据访问对象
DAO层可以做CRUD操作。它可以对我们的表进行增删改查。
我们的DAO层接口应该像这样:
<code class="java">public interface UserDao { User getUser(); Set<user> getAllUsers(); User getUserByUserNameAndPassword(); boolean insertUser(); boolean updateUser(); boolean deleteUser(); }</user></code>
查找用户
用户可以通过像ID,姓名或邮箱等任何唯一字段来查询。在这个例子中,我们使用ID来查找用户。第一步是通过连接器类来创建一个connection,然后执行SELECT语句以获得其ID为7的用户,我们可以使用这条语句查询用户:
<code class="sql">SELECT * FROM user WHERE id=7</code>
就在这里,我们做了一个动态的语句来从参数中获取ID。
通过执行这个查询,得到一个结果集,其中保存有用户或null。我们可以通过Resultset的next()方法来检测是否有值。如果返回true,我们将继续利用data getters从ResultSet中获取用户数据。当我们将所有的数据封装到user中后,我们返回它。如果不存在此ID的用户或其他任何异常发生(如无效的SQL语句)这个方法会返回null。
<code class="java">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; }</code>
使用单独的方法来从结果集中提取数据将会更方便,因为在很多方法中我们将会调用它。
这个新方法将抛出SQLException并且为了限制只能在类内部使用,其应该是私有的:
<code class="java">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; }</code>
我们上面的方法应该修改成新的方法:
<code class="java">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; }</code>
登陆方法
登陆操作类似。我们希望提供用户和密码替代ID,这将不会影响参数列表和查询语句。如果用户名和密码是正确的,这个方法会返回一个有效的用户,否则为null。因为有很多的参数,使用PreparedStatement将更有用。
<code class="java">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; }</code>
查询所有用户的方法
这个方法将会返回所有的用户,所以我们应该将它们存在一个类似数组的容器中返回来。但是,因为我们不知道有多少条记录。 使用例如Set或者List的集合将会更好:
<code class="java">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; }</code>
插入方法
Insert方法将采取用户作为参数,并使用PreparedStatement对象来执行SQL update语句。executeUpdate 方法返回受影响的行数。如果我们添加单行,意味着该方法应该返回1,如果是这样,我们返回true,否则,我们返回false
<code class="java">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; }</code>
更新方法
更新方法和插入方法类似。唯一变化的是SQL语句
<code class="java">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; }</code>
删除方法
删除的方法是使用一个简单的查询像
<code class="sql">DELETE FROM user WHERE ID = 7</code>
带上id参数发送该查询将删除此记录。如果成功删除将返回1
<code class="java">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; }</code>

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。
