JDBC
什么是JDBC
其实JDBC就是一套统一的java代码,这套代码,可以操作所有的关系型数据库。
接口需要实现类,每一个不同的数据库产商定义了不同的实现类,但是每一个实现类都实现类了相同的JDBC接口。
我们写代码的时候,只需要实现接口的调用,实现类是由不同的数据库厂商来实现的。(实现类也叫数据库驱动)
JDBC的本质
官方(sun)公司定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行代码是驱动jar包中的实现类。
两个层次:
面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
JDBC驱动程序:各个数据库厂商根据JDBC的规范制作的 JDBC 实现类的类库
JDBC驱动程序总共有四种类型:
第一类:JDBC-ODBC桥。
第二类:部分本地API部分Java的驱动程序。
第三类:JDBC网络纯Java驱动程序。
第四类:本地协议的纯 Java 驱动程序。
JDBC常用的API
一、Driver接口
Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。
在编写JDBC程序时,必须把所使用的数据库驱动程序或者类库加载到项目的classpath中(这里指MySQL驱动JAR包)
二、DriverManager类
DriverManager类用于加载JDBC驱动,并且创建与数据库的连接
在DriverManager类中,定义了两个比较重要的静态方法。
方法名称 | 功能描述 |
---|---|
static void registerDriver(Driver driver) | 该方法用于向DriverManager中注册给定的JDBC驱动程序 |
static Connection getConnection(String url,String user,String pwd) | 该方法用于建立和数据库的连接,并返回表示连接的Connection对象 |
三、Connection接口
Connection接口代表Java程序和数据库的连接,只有获得该连接对象后,才能访问数据库,并操作数据表
方法名称 | 功能描述 |
---|---|
DatabaseMetaData getMetaData() | 该方法用于返回表示数据库的元数据的DatabaseMetaData对象 |
Statement createStatement() | 用于创建一个Statement对象来将SQL语句发送到数据库 |
PreparedStatement preparStatement(String sql) | 用于创建一个PreparedStatement对象来将参数化的SQL语句发送到数据库 |
CallableStatement prepareCall(String sql) | 用于创建一个CallableStatement对象来调用数据库存储过程 |
四、Statement接口
Statement接口用于执行静态的SQL语句,并返回一个结果对象。
Statement接口对象可以通过Connection实例的createStatement()方法获取,该对象会把静态的SQL语句发送到数据库中编译执行,然后返回数据库的处理结果。
在Statement接口中,提供了3个常用的执行SQL语句的方法
方法名称 | 功能描述 |
---|---|
boolean execute(String sql) | 用于执行各种SQL语句,该方法返回一个Boolean类型的值,如果为true,表示所执行的SQL语句有查询结果,可通过Statement的getResultSet()方法获得查询结果 |
int executeUpdate(String sql) | 用于执行SQL中的insert、update和delete语句。该方法返回一个int类型的值,表示数据库中受该SQL语句影响的记录条数 |
ResultSet executeQuecry(String sql) | 用于执行SQl中的select语句,该方法返回一个表示查询结果的ResultSet对象 |
五、PreparedStatement接口
PreparedStatement 是 Statement的子接口,用于执行预编译的SQL语句。
该接口扩展了带有参数SQL语句的执行操作,应用该接口中的SQL语句可以使用占位符 “?” 来替代其参数,然后通过 setXxx()方法为SQL 语句的参数赋值。
方法名称 | 功能描述 |
---|---|
int executeUpdate() | 在此PreparedStatement对象中执行SQL语句,该语句必须是一个DML语句或者是无返回内容的SQL语句,如DDL语句 |
ResultSet executeQuery() | 在此PreparedStatement对象中执行SQL查询,该方法返回的是ResultSet对象 |
void setInt(int parameterIndex,int x) | 将指定参数设置为给定的int值 |
void setFloat(int parameterIndex,float x) | 将指定参数设置为给定的float值 |
void setString(int parameterIndex,String x) | 将指定参数设置为给定的String值 |
void setDate(int parameterIndex,Date x) | 将指定参数设置为给定的Date值 |
将一组参数添加到此Pre对象的处理命令 |
在通过setXxx()方法为SQL语句中的参数赋值时,可以通过输入参数的已定义SQL类型兼容的方法(例如,如果参数具有SQL类型为Integer,那么应该使用setInt()方法,也可以通过setObject()方法设置多种类型的输入参数)
需要注意的是,表中的setDate()方法可以设置日期内容,但参数Date的类型是java.sql.Date,而不是java.util.Date
六、ResultSet接口
ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装再一个逻辑表格中。在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时,游标在表格的第一行之前,调用next()方法作为while循环的条件来迭代ResultSet结果集。ResultSet接口中的常用方法如下所示。
ResultSet接口定义了大量的getXxx()方法,而采用哪种getXxx()方法取决于字段的数据类型。程序既可以通过字段的名称来获取指定数据,也可以通过字段的索引来获取指定的数据,字段的索引是从1开始编号的。例如,数据表的第一列字段名为id,字段类型为int,那么既可以使用getInt(1)获取该列的值,也可以使用getInt(“id”)获取该列的值。
实现第一个JDBC程序
1.搭建数据库环境
在MySQL中创建一一个名称为jdbc 的数据库,然后在该数据库中创建一一个users表,并向其插入数据
2.创建项目环境,导入数据库驱动
在Eclipse中新建一一个名称为chapter09的Web项目,将下载好的MySQL的数据库驱动文件mysql-connector-java-5.0.8- bnjan复制到项目的ib目录中,并发布到类路径下(MsSQL驱动文件可以在其官网地址: ht:/:/v.mysal.om/downloadsco.e.cor/页面中下载在浏览器中输入该地址后即可进入下载页面,单击页面Generally Available (GA) Releases窗口中的Looking for previous GA versions超链接后,在显示出的下拉框中下载所需的驱动版本即可
编写JDBC程序
在项目chapter09的srC目录下,新建一一个名称为cn.itcast.jdbc.example的包,在该包中创建类Example01,该类用于读取数据库中的users表,并将结果输出到控制台
package cn.itcast.jbdc.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Example01 {
public static void main(String[] args) throws SQLException {
Statement stmt=null;
ResultSet rs=null;
Connection conn=null;
try {
//1.注册数据库的驱动
Class.forName("com.mysql.jdbc.Driver");
//2.通过DriverManager获取数据库连接
String url = "jdbc:mysql://localhost:3306/jdbc";
String username = "root";
String password = "123456";
conn=DriverManager.getConnection(url, username, password);
//3.通过Connection对象获取Statement对象
stmt=conn.createStatement();
//4.使用Statement执行SQL语句
String sql="select * from users";
rs=stmt.executeQuery(sql);
//5.操作ResultSet结果集
System.out.println("id | name | password | email | birthday");
while (rs.next()) {
int id=rs.getInt("id"); //通过列名获取指定字段的值
String name = rs.getString("name");
String psw = rs.getString("password");
String email = rs.getString("email");
String birthday = rs.getString("birthday");
System.out.println(id + " | " + name + " | " + psw + " | " + email + " | " + birthday);
}
}catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
//6.回收数据库资源
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs=null;
}
if(stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt=null;
}
if(conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn=null;
}
}
}
}
PreparedStatement 对象
创建一个名称为Example02的类,在该类中使用PreparedStatement 对象对数据库进行插入数据的操作
package cn.itcast.jbdc.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Example02 {
public static void main(String[] args) throws SQLException {
Connection conn=null;
PreparedStatement preStmt=null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/jdbc";
String username="root";
String password="123456";
//创建应用程序与数据库连接的Connection对象
conn = DriverManager.getConnection(url, username, password);
//执行的SQL语句
String sql="INSERT INTO users(name,password,email,birthday)"
+ "VALUES(?,?,?,?)";
//创建执行SQL语句的PreparedStatement对象
preStmt=conn.prepareStatement(sql);
preStmt.setString(1, "zl");
preStmt.setString(2, "123456");
preStmt.setString(3, "zl@sina.com");
preStmt.setString(4, "1789-12-23");
preStmt.executeUpdate();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally { //释放资源
if (preStmt != null) {
try {
preStmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
preStmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
}
ResultSet 对象
ResultSet主要用于存储结果集,可以通过nex:()方法由前向后逐个获取结果集中的数据。如果想获取结果集中任意位置的数据,则需要在创建Statement对象时,设置两个ResutSet定义的常量,具体设置方式如下。
创建一个名称为Example03 的类,该类中使用ResultSet对象取出指定数据的信息
package cn.itcast.jbdc.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Example03 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/jdbc";
String username = "root";
String password = "123456";
//1.获取Connection对象
conn = DriverManager.getConnection(url, username, password);
String sql = "select * from users";
//2.创建Statement对象并设置常量
Statement st=conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
//3.执行SQL并将获取的数据信息存放在ResultSet中
ResultSet rs=st.executeQuery(sql);
//4.取出ResultSet中指定数据的信息
System.out.println("第2条数据的name值为:");
rs.absolute(2); //将指针定位到结果集中的第2行数据
System.out.println(rs.getString("name"));
System.out.println("第1条数据的name值为:");
rs.beforeFirst(); //将指针定位到结果集中的第1行数据之前
rs.next(); //将指针向后滚动
System.out.println(rs.getString("name"));
System.out.println("第4条数据的name值为:");
rs.afterLast(); //将指针定位到结果集中最后一条数据之后
rs.previous(); //将指针向前滚动
System.out.println(rs.getString("name"));
} catch (Exception e) {
e.printStackTrace();
} finally { //释放资源
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
}
创建一个名称为example03test的类,该类中使用ResultSet对象取出指定数据的信息
package cn.itcast.jbdc.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class example03test {
public static void main(String[] args) {
Connection con=null;
Statement stmt=null;
ResultSet rs=null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","123456");
//3.获取查询数据库
stmt=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
//4.执行查询语句
rs=stmt.executeQuery("select * from users");
rs.absolute(2);
System.out.println("第二行的数据"+rs.getString("name"));
rs.beforeFirst();
rs.next();
System.out.println("第一行的数据"+rs.getString("name"));
rs.afterLast();
rs.previous();
System.out.println("最后一行"+rs.getString("name"));
}catch(Exception e) {
throw new RuntimeException(e);
}finally {
//6.关闭连接,释放资源
System.out.println("资源会被关闭吗----");
if(rs!=null) {
}
}
}
}
使用JDBC完成数据的增删改查
1.创建JavaBean
创建一个用于保存用户数据的User类
package cn.itcast.jbdc.example;
import java.sql.Date;
public class User {
private int id;
private String username;
private String password;
private String email;
private Date birthDay;
public int grtId() {
return id;
}
public void setId(int id) {
this.id=id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username=username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password=password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email=email;
}
public Date getBirthDay() {
return birthDay;
}
public void setBirthDay(Date birthDay) {
this.birthDay=birthDay;
}
}
2.创建工具类
由于每次操作数据库时,都需要加载数据库驱动、建立数据库连接以及关闭数据库连接,为了避免代码的重复书写,下面建立一个专门用于数据库相关操作的工具类
创建JDBCUtils工具类
package cn.itcast.jbdc.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtils {
//获取连接对象的方法
public static Connection getCon() throws Exception{
//1.注册和加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","123456");
return con;
}
//关闭连接,释放资源
public static void realse(ResultSet rs,Statement stmt,Connection con) {
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt=null;
}
if(con!=null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
con=null;
}
}
}
3.创建DAO
创建一个名称为UsersDao的类,该类中封装了对表users 的添加、查询、删除和更新等操作
package cn.itcast.jbdc.example;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
public class UsersDao {
//添加用户的操作
public boolean insert(User user) {
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//获得数据的连接
conn=JDBCUtils.getCon();
//获得Statement对象
stmt=conn.createStatement();
//发送SQL语句
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String birthday=sdf.format(user.getBirthDay());
String sql="INSERT INTO users(id,name,password,email,birthday) "+
"VALUES("
+user.getId()+",'"
+user.getUsername()+"','"
+user.getPassword()+"','"
+user.getEmail()+"','"
+birthday + "')";
int num=stmt.executeUpdate(sql);
if(num>0) {
return true;
}
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.realse(rs, stmt, conn);
}
return false;
}
//查询所有的User对象
public ArrayList<User> findAll() {
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
ArrayList<User> List = new ArrayList<User>();
try {
//获得数据的连接
conn=JDBCUtils.getCon();
//获得Statement对象
stmt=conn.createStatement();
//发送SQL语句
String sql = "SELECT * FROM users";
rs = stmt.executeQuery(sql);
//处理结果集
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setBirthDay(rs.getDate("birthday"));
List.add(user);
}
return List;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.realse(rs, stmt, conn);
}
return null;
}
//根据id查找指定的user
public User find(int id) {
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//获得数据的连接
conn=JDBCUtils.getCon();
//获得Statement对象
stmt=conn.createStatement();
//发送SQL语句
String sql = "SELECT * FROM users WHERE id=" + id;
rs = stmt.executeQuery(sql);
//处理结果集
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setBirthDay(rs.getDate("birthday"));
return user;
}
return null;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.realse(rs, stmt, conn);
}
return null;
}
//删除方法
public boolean delete(int id) {
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//获得数据的连接
conn=JDBCUtils.getCon();
//获得Statement对象
stmt=conn.createStatement();
//发送SQL语句
String sql="DELETE FROM users WHERE id=" + id;
int num=stmt.executeUpdate(sql);
if(num>0) {
return true;
}
return false;
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.realse(rs, stmt, conn);
}
return false;
}
//修改用户
public boolean update(User user) {
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//获得数据的连接
conn=JDBCUtils.getCon();
//获得Statement对象
stmt=conn.createStatement();
//发送SQL语句
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String birthday=sdf.format(user.getBirthDay());
String sql="UPDATE users set name='" + user.getUsername()
+ "',password='" + user.getPassword() + "',email='"
+user.getEmail() + "',birthday='" + birthday
+ "' WHERE id=" + user.getId();
int num=stmt.executeUpdate(sql);
if(num>0) {
return true;
}
return false;
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.realse(rs, stmt, conn);
}
return false;
}
}
4.创建测试类
编写测试类JdbcInsertTest实现向users 表中添加数据的操作
package cn.itcast.jbdc.example;
import java.sql.Date;
import cn.itcast.jbdc.example.UsersDao;
import cn.itcast.jbdc.example.User;
public class JdbcInsertTest {
public static void main(String[] args) {
//向user表插入一个用户信息
UsersDao ud=new UsersDao();
User user=new User();
user.setId(5);
user.setUsername("hl");
user.setPassword("123");
user.setEmail("hl@sina.com");
user.setBirthDay(new Date());
boolean flag=ud.insert(user);
System.out.println(flag);
}
}
编写测试类FindAllUsersTest,该类用于实现读取users
package cn.itcast.jbdc.example;
import java.util.ArrayList;
public class FindAllUserTest {
public static void main(String[] args) {
//创建一个名称为usersDao的对象
UsersDao usersDao=new UsersDao();
//将UsersDao对象的findAll()方法执行后的结果放入list集合
ArrayList<User> list = usersDao.findAll();
//循环输出集合中的数据
for (int i = 0; i < list.size(); i++) {
System.out.println("第" + (i + 1) + "条数据的username值为:"
+ list.get(i).getUsername());
}
}
}
编写测试类FindUserByldTest,在该类中实现读取users表中指定的数据
package cn.itcast.jbdc.example;
public class FindUserByldTest {
public static void main(String[] args) {
UsersDao usersDao = new UsersDao();
User user = usersDao.find(1);
System.out.println("id为1的User对象的name值为:" + user.getUsername());
}
}
编写测试类UpdateUserTest,在该类中实现修改sers表中数据的操作
package cn.itcast.jbdc.example;
public class UpdateUserTest {
public static void main(String[] args) {
//修改User对象的数据
UsersDao usersDao = new UsersDao();
User user = new User();
user.setId(4);
user.setUsername("zhaoxiaoliu");
user.setPassword("456");
user.setEmail("zhaoxiaoliu@sina.com");
user.setBirthDay(new Date());
boolean b = usersDao.update(user);
System.out.println(b);
}
}
编写测试类DeleteUserTest, 该类实现了删除users表中数据的操作
package cn.itcast.jbdc.example;
public class DeleteUserTest {
public static void main(String[] args) {
//删除操作
UsersDao usersDao=new UsersDao();
boolean b = usersDao.delete(4);
System.out.println(b);
}
}