阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

简单的JDBC实例分享

125次阅读
没有评论

共计 9453 个字符,预计需要花费 24 分钟才能阅读完成。

前言:安装好数据库之后,我们编写的 Java 程序是不能直接使用数据库的,而 JDBC(Java Database Connectivity, 即 java 数据库连接)是 java 语言里用来规范客户端程序访问数据库的 API,有了它,我们就可以向各种关系型数据库发送 SQL 语句,从而实现对数据库的增删改查等操作。

准备工作:

1. 数据库: 这里以 MySQL 为例,创建一个 Person 表,四个字段分别为:自增主键 id、姓名 name、性别 gender、年龄 age

DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  `gender` varchar(11) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

INSERT INTO `person` VALUES (‘1’, ‘ 小明 ’, ‘ 男 ’, ’18’);
INSERT INTO `person` VALUES (‘2’, ‘ 小芳 ’, ‘ 女 ’, ’19’);
INSERT INTO `person` VALUES (‘3’, ‘ 小刚 ’, ‘ 男 ’, ’20’);
INSERT INTO `person` VALUES (‘4’, ‘ 小丽 ’, ‘ 女 ’, ’21’);

2. 数据库驱动程序 jar 包:这里使用的是 mysql-connector-java-5.1.42-bin.jar

3. 在 eclipse 中导入驱动包:右键项目点击 Builder Path—-Configure Builder Path—-Add External JARs—- 找到 jar 包位置选择打开 —-Ok, 可以开始搞事情了!

图示如下:

简单的 JDBC 实例分享

先完整演示一段简单的 JDBC 操作过程。

package com.jdbc.demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

// 一段完整的 jdbc 操作过程, 后面会详细介绍,为了代码视图简洁,异常均抛出。
public class Demo {
   
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 第 1 步,注册加载驱动类
        Class.forName(“com.mysql.jdbc.Driver”);
        // 第 2 步,获取数据库连接, 方法中 3 个参数依次为:
        //url: 就是你要连接的数据库的地址,不同的数据库格式会有差异
        //user: 就是数据库的用户名,例如 MySQL 的 root
        //password: 数据库连接密码
        String url = “jdbc:mysql://127.0.0.1/hb?characterEncoding=utf-8”;
        String user = “root”;
        String password = “123123”;
        Connection conn = DriverManager.getConnection(url, user, password);
        // 第 3 步,构造语句集对象,为了简要直观,这里使用 Statement, 不过实际开发建议用 PreparedStatement
        String sql = “select * from person”;
        Statement stmt = conn.createStatement();
        // 第 4 步,提交 SQL 语句,这是是查询,所以调用 executeQuery 方法,会返回一个集合,我们可以遍历输出其中信息;
        // 如果是增删改,不同于数据库中的 3 种 SQL 语句,这里都是调用 executeUpdate 方法,返回的是 int 值
        ResultSet rs = stmt.executeQuery(sql);
        // 第 5 步 (可选),处理结果,在这里我们输出 Person 表中所有人名
        while(rs.next()) {
            String name = rs.getString(“name”);
            System.out.println(name);
        }
        // 第 6 步,关闭相关对象,这里为 ResultSet,Statement,Connection
        // 注意!关闭顺序和声明顺序相反! 依次如下
        rs.close();
        stmt.close();
        conn.close();
       
    }

}

程序运行结果如下:

简单的 JDBC 实例分享

 相关 API 介绍

java.sql.Connection:

与数据库的连接,注意导包不要导错,因为导入 MySQL 驱动后,在 com.mysql.jdbc 下也有个 Connection, 如果导成这个会出错;

连接由 JDBC 管理层的 DriverManager 类调用 getConnection 方法获得,方法中后两个参数比较简单,一个用户名一个密码,第一个参数 url 格式则与各数据库有关

MySQL: jdbc:mysql://<host><:port>/<database_name>, 默认端口 3306,如果服务器使用默认端口则 port 可以省略, 可以在 URL 中添加额外的连接属性 jdbc:mysql://<host>:<port>/<database_name>?property1=value1&property2=value2;

Oracle:jdbc:oracle:thin:@<host><:port>:<database_name>

java,sql.Statement 和 java.sql.PreparedStatement

语句对象,用于提交 SQL 语句;

Statement 通常用于执行静态 SQL 语句,statement.excute(sql) 即可提交;

PreparedStatement 可以执行动态 SQL 语句,允许参数化查询,而且性能更好,还可以有效避免 SQL 注入式攻击,后面示例都使用 PreparedStatement

简单的 JDBC 实例分享

 

java.sql.ResultSet:

指定 SQL 语句(通常为查询)执行返回的原始结果集,在实际开发我们通常对结果进行再封装,以方便调用

实体类 Person

package com.jdbc.entity;
// 实体类 Person,属性与数据库中字段对应
public class Person {
    private Integer id;
    private String name;
    private String gender;
    private Integer 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 getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return “Person [id=” + id + “, name=” + name + “, gender=” + gender
                + “, age=” + age + “]”;
    }
   
}

JdbcUtil 工具类供加载驱动类、获取连接、关闭对象

package com.jdbc.demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JdbcUtil {
    private static String driver = “com.mysql.jdbc.Driver”;
    private static String url = “jdbc:mysql://127.0.0.1/hb?characterEncoding=utf-8”;
    private static String username = “root”;
    private static String password = “hjh123”;
    // 静态代码块中注册加载驱动类
    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    // 封装获取连接方法
    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 封装关闭对象方法
    public static void close(ResultSet rs, Statement statement, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

   
}

简易封装一个 DAO 类实现对 Person 表的增删改查

 

package com.jdbc.demo;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.jdbc.entity.Person;

// 封装 Person 表的增删改查方法
public class PersonDaoImpl {
    // 这里的问号? 是占位符, 用于给将要传递的参数占位置,实现了动态 SQL 语句的执行
    // 添加一条记录的 SQL 语句,第一个参数由于数据表中是主键自增,这里可以用 null
    private static final String SQL_ADD = “insert into person values(null,?,?,?)”;
    // 删除,指定 id 的记录
    private static final String SQL_DEL = “delete from person where id = ?”;
    // 修改,指定 id 的记录
    private static final String SQL_UPD = “update person set name = ?,gender = ?,age = ? where id = ?”;
    // 查询,指定 id 记录
    private static final String SQL_ID = “select * from person where id = ?”;
    // 查询,所有记录
    private static final String SQL_ALL = “select * from person”;
   
    // 添加一条记录
    public boolean add(Person p) {
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(SQL_ADD);
            // 把我们传入的 person 对象的属性值分作为占位符的值传入, 数组各值顺序对应占位符字段顺序
            Object[] params = {p.getName(),p.getGender(),p.getAge()};
            int len = params.length;
            for(int i = 0;i < len;i++) {
                //!!!这里比较特殊,很多下标都是从 0 开始,例如数组,
                //!!!但是这个 setObject 方法第一个索引参数是从 1 开始
                ps.setObject(i+1, params[i]);
            }
            // 这里的整型返回值 line 意指更新的记录数,或者说是数据库中受影响的记录行数
            // 之前的 Statement.excute 方法要传入 SQL 语句字符串参数,
            // 但是用了 PreparedStatement 就不用传参数了,因为在前面我们已经预定义处理了
            int line = ps.executeUpdate();
            if (line > 0) {
                System.out.println(“ 添加成功, 受影响记录数为 ”+line);
                return true;// 结束,但是后面 finally 区代码会执行
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭相关对象
            JdbcUtil.close(null, ps, conn);
        }
        System.out.println(“ 添加失败 ”);
        return false;
    }
    // 删除一条记录
    public boolean delete(int id) {
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(SQL_DEL);
            ps.setInt(1, id);
            // 这里的整型返回值 line 意指更新的记录数,或者说是数据库中受影响的记录行数
            int line = ps.executeUpdate();
            if (line > 0) {
                System.out.println(“ 删除成功, 受影响记录数为 ”+line);
                return true;// 结束,但是后面 finally 区代码会执行
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭相关对象
            JdbcUtil.close(null, ps, conn);
        }
        System.out.println(“ 删除失败 ”);
        return false;
    }
    // 修改一条记录
    public boolean update(Person p) {
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(SQL_UPD);
            // 把我们传入的 person 对象的属性值分作为占位符的值传入
            Object[] params = {p.getName(),p.getGender(),p.getAge(),p.getId()};
            int len = params.length;
            for(int i = 0;i < len;i++) {
                //!!!这里比较特殊,很多下标都是从 0 开始,例如数组,
                //!!!但是这个 setObject 方法第一个索引参数是从 1 开始
                ps.setObject(i+1, params[i]);
            }
            // 这里的整型返回值 line 意指更新的记录数,或者说是数据库中受影响的记录行数
            int line = ps.executeUpdate();
            if (line > 0) {
                System.out.println(“ 修改成功, 受影响记录数为 ”+line);
                return true;// 结束,但是后面 finally 区代码会执行
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭相关对象
            JdbcUtil.close(null, ps, conn);
        }
        System.out.println(“ 修改失败 ”);
        return false;
    }
    // 获取一条记录, 这里返回的不再是布尔值,而是一个对应数据表中一条记录的 Person 对象
    public Person findById(int id) {
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(SQL_ID);
            ps.setInt(1, id);
            // 返回结果集,这里是查询指定 id,所以结果集中应该最多只有一条记录
            rs = ps.executeQuery();
            if(rs.next()) {
                Person p = new Person();
                p.setId(id);
                // 这里的 Result 的 getObject 方法,参数为数据表中字段名,可以获取对应字段值
                p.setName(rs.getString(“name”));
                p.setGender(rs.getString(“gender”));
                p.setAge(rs.getInt(“age”));
                return p;// 返回 p 对象,结束
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭相关对象
            JdbcUtil.close(rs, ps, conn);
        }
        return null;
    }
    // 获取所有记录,返回结果集不便操作,故封装到一个 List 中作为方法返回值
        public List<Person> findAll() {
            Connection conn = JdbcUtil.getConnection();
            PreparedStatement ps = null;
            ResultSet rs = null;
            List<Person> list = new ArrayList<>();
            try {
                ps = conn.prepareStatement(SQL_ALL);
                // 返回结果集
                rs = ps.executeQuery();
                while(rs.next()) {
                    // 创建一个 Person 对象
                    Person p = new Person();
                    // 这里的 Result 的 getObject 方法,参数为数据表中字段名,可以获取对应字段值
                    p.setId(rs.getInt(“id”));
                    p.setName(rs.getString(“name”));
                    p.setGender(rs.getString(“gender”));
                    p.setAge(rs.getInt(“age”));
                    list.add(p);// 添加至集合
                }
                return list;
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                // 关闭相关对象
                JdbcUtil.close(rs, ps, conn);
            }
            return null;
        }
}

 小结

JDBC 操作数据库步骤概述如下:

1. 注册加载驱动类

2. 获取连接

3. 创建语句对象

4. 执行 SQL 语句(excute)

5(可选). 处理结果

6. 关闭相关对象(注意顺序:依次为 ResultSet、Statement/PreparedStatement、Connction)

扩展

上述过程能基本完整实现对一个数据表的操作,但是只能针对固定的单个数据表,利用泛型、反射等技术,可对 dao 层代码进行抽取和封装,添加 SQL 语句实现联表查询,使得程序更具有通用性和灵活性,对任意的数据表都适用。在实际开发过程中,有框架已经封装了 JDBC,如 hibernate 和 mybatis,可以通过底层的 JDBC 操作进一步学习。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2017-07/145806.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-22发表,共计9453字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中