gpt4 book ai didi

java 使用JDBC构建简单的数据访问层实例详解

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章java 使用JDBC构建简单的数据访问层实例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

本教程的目的是使用Java编写的分离的层去访问数据库中的表,这一层通常称为数据访问层(DAL) 。

使用DAL的最大好处是通过直接使用一些类似insert()和find()的方法简化了数据库的访问操作,而不是总是先做链接,再执行一些查询.

该层在其内部处理所有与数据库相关的调用和查询.

创建数据库 。

我们希望为用户创造一个简单的表,我们可以使用这些字段来创建 。

id        int name      varchar(200) password  varchar(200) age       int   。

数据传输对象 。

这一层应该包含一个简单的类叫做数据传输对象(DTO)。这个类仅仅是一个与数据库中的表相对应的简单映射,表中的每一列对应类的一个成员变量.

我们的目的是使用简单的Java对象,而不是处理SQL语句和其他与数据库相关的命令来进行数据库的增删改查.

我们想要把表映射成java代码,只需要创建包含相同字段的类(bean)即可 。

为了更好地封装,除了构造函数我们应该声明所有字段变量为私有,创造访问器(getter和setter),其中有一个是默认的构造函数.

?
1
2
3
4
5
6
public class User {
   private Integer id;
   private String name;
   private String pass;
   private Integer age;
}

为了正确地映射字段,我们应该考虑数据库中的NULL值。对于Java的原始的默认值,例如int类型,其默认值是0,所以我们应该提供可容纳空值的新的数据类型。我们可以通过使用特殊的类型——封装类,如Integer来代替 INT.

最后我们的类应该像这样:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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又或者抛出一个运行时异常.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
   }
}

我们也可以在类中包含一个主方法来测试连接。完整的类像这样:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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层接口应该像这样:

?
1
2
3
4
5
6
7
8
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.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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并且为了限制只能在类内部使用,其应该是私有的:

?
1
2
3
4
5
6
7
8
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;
}

我们上面的方法应该修改成新的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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将更有用.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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的集合将会更好:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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语句 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 ;
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持! 。

最后此篇关于java 使用JDBC构建简单的数据访问层实例详解的文章就讲到这里了,如果你想了解更多关于java 使用JDBC构建简单的数据访问层实例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com