| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
jopen
9年前发布

使用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;  }

 本文由用户 jopen 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
 转载本站原创文章,请注明出处,并保留原始链接、图片水印。
 本站是一个以用户分享为主的开源技术平台,欢迎各类分享!
 本文地址:https://www.open-open.com/lib/view/open1453189138620.html
JDBC Java开发