前言:安装好数据库之后,我们编写的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 ('', '小明', '男', '');
INSERT INTO `person` VALUES ('', '小芳', '女', '');
INSERT INTO `person` VALUES ('', '小刚', '男', '');
INSERT INTO `person` VALUES ('', '小丽', '女', '');

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

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

图示如下:

先完整演示一段简单的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(); } }

程序运行结果如下:

相关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

  

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操作进一步学习。

一颗简单的JDBC栗子的更多相关文章

  1. 一颗简单的hibernate栗子

    Hibernate是一个开源的ORM框架,顾名思义,它的核心思想即ORM(Object Relational Mapping,对象关系映射),可以通过对象来操作数据库中的信息,据说开发者一开始是不太熟 ...

  2. 简单通用JDBC辅助类封装

    哎,最近很好久没在博客园写点东西了,由于工作的原因,接触公司自己研发的底层orm框架,偶然发现该框架在调用jdbc操作的时候参考的是hibernate 里面的SimpleJdbcTemplate,这里 ...

  3. 简单的JDBC编程步骤

    1.加载数据库驱动(com.mysql.jdbc.Driver) 2.创建并获取数据库链接(Connection) 3.创建jdbc statement对象(PreparedStatement) 4. ...

  4. java使用注解和反射打造一个简单的jdbc工具类

    a simple jdbc tools 如有转载和引用,请注明出处,谢谢 1. 定义我们需要的注解 要想实现对数据库的操作,我们必须知道数据表名以及表中的字段名称以及类型,正如hibernate 使用 ...

  5. 编写一个简单的 JDBC 程序

    连接数据库的步骤: 1.注册驱动(只做一次) 2.建立连接(Connection) 3.创建执行SQL的语句(Statement) 4.执行语句 5.处理执行结果(ResultSet) 6.释放资源 ...

  6. 【Java编程】建立一个简单的JDBC连接-Drivers, Connection, Statement and PreparedStatement

    本blog提供了一个简单的通过JDBC驱动建立JDBC连接例程.并分别通过Statement和PreparedStatement实现对数据库的查询. 在下一篇blog中将重点比較Statement与P ...

  7. 自定义一个简单的JDBC连接池

    一.什么是JDBC连接池? 在传统的JDBC连接中,每次获得一个Connection连接都需要加载通过一些繁杂的代码去获取,例如以下代码: public static Connection getCo ...

  8. 在简单的JDBC程序中使用ORM工具

    本文来自[优锐课]——抽丝剥茧,细说架构那些事. ORM(对象关系映射)是用于数据库编程的出色工具.只需一点经验和Java注释的强大功能,我们就可以相对轻松地构建复杂的数据库系统并利用生产力.关系数据 ...

  9. 在Eclipse上实现简单的JDBC增删查改操作

    在Javaweb的学习里,学到了如何完成简单的增删查改操作,在这里撰写一篇文章以便自己整理回忆. 首先要建立一些包和导入一些文件.建一些类.具体框架如图  编写Product类 public clas ...

随机推荐

  1. WebSocket和kafka实现数据实时推送到前端

    一. 需求背景      最近新接触一个需求,需要将kafka中的数据实时推送到前端展示.最开始想到的是前端轮询接口数据,但是无法保证轮询的频率和消费的频率完全一致,或造成数据缺失等问题.最终确定用利 ...

  2. JVM点滴

    JVM java拥有GC,为什么还会内存泄漏? 理解什么是内存泄漏: Java中的内存泄露,广义并通俗的说,就是:不再会被使用的对象的内存不能被回收,就是内存泄露. Java为了简化编程工作,对于不再 ...

  3. css颜色值设置方式有哪些?以及如何随机一个颜色?

    网页中颜色的使用方式有一下几种 1.颜色名称 ,如red  black white 2.十六进制颜色,网页中常用,每两位代表红绿蓝的值的比例,  如 #ffffff白色   #000000黑色 3.r ...

  4. nodeJS之流stream

    前面的话 当内存中无法一次装下需要处理的数据时,或者一边读取一边处理更加高效时,我们就需要用到数据流.NodeJS中通过各种Stream来提供对数据流的操作.本文将详细说明NodeJS中的流strea ...

  5. 黑马程序员:3分钟带你读懂C/C++学习路线

    随着互联网及互联网+深入蓬勃的发展,经过40余年的时间洗礼,C/C++俨然已成为一门贵族语言,出色的性能使之成为高级语言中的性能王者.而在今天,它又扮演着什么样重要的角色呢?请往下看: 后端服务器,移 ...

  6. jquery不兼容input的change事件处理

    因为客户使用系统一般都是用IE版本的浏览器,所以每次在chrome下调试之后都要在IE走一遍; 这次准备在选择开始时间或者结束时间之后在下方能及时给出对应的天数,但是在IE8下试了change时间根本 ...

  7. 用excel公式生成有规律的代码,减少编程工作量

    1.在excel中如何输入公式 在excel表格中输入 & 符号是字符串的连接符,比如: 在excel表格中输入  ="sherlock"&"mina&q ...

  8. window.close()方法对谷歌和火狐浏览器无效

    在近期的项目中,遇到了一个问题,就是用户到新浪支付进行操作,操作成功后,指定到一个网页,需求是点击确定,关闭该网页.需求出来以后认为这种就是小菜一碟,直接用 window.close()方法就可以实现 ...

  9. JS 冒泡排序从学到优化

    目的:理解算法 深化算法 冒泡排序: 直接上动图好于文字 一个冒泡实例 45,67,23,88,21,6,99// 第一轮 6次// 45 67 23 88 21 6 99// 45 23 67 88 ...

  10. 点击页面其它地方隐藏该div的方法

    思路一 第一种思路分两步 第一步:对document的click事件绑定事件处理程序,使其隐藏该div 第二步:对div的click事件绑定事件处理程序,阻止事件冒泡,防止其冒泡到document,而 ...