关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »使用JDBC构建简单的数据访问层

    使用JDBC构建简单的数据访问层

    2016-01-17 00:00:00 出处:有梦想的咸鱼
    分享

    以下是如何使用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;
    }
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。