java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言, 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台 (即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se)) 的总称
以下是如何使用 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.phperz.com/article/18/0213/359410.html