1,JDBC概述和接口
1.1,JDBC简介
什么是JDBC?
- Java Database Connectivity
- JDBC是Java访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动,每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用JDBC接口中的方法即可,数据库驱动由数据库厂商提供。
使用JDBC的好处
- 程序员如果要开发访问数据库的程序,只需要会调用JDBC接口中的方法即可,不用关注类是如何实现的。
- 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库。
使用JDBC开发使用到的包
包名 |
内容概述 |
java.sql |
所有与JDBC访问数据库相关的接口和类 |
javax.sql |
数据库拓展包,提供数据库额外的功能。比如:连接池 |
数据库的驱动 |
由各大数据库厂商提供,需要额外去下载,是对JDBC接口实现的类 |
JDBC核心API
接口或类 |
作用 |
DriverManager类 |
1,管理和注册数据库驱动。2,得到数据库连接对象。 |
Connection接口 |
一个连接对象,可用于创建Statement和PreparedStatement对象 |
Statement接口 |
一个SQL语句对象,用于将SQL语句发送给数据库服务器 |
PreparedStatement接口 |
一个SQL语句对象,是Statement的子接口 |
ResultSet接口 |
用于封装数据库查询的结果集,返回给客户端Java程序 |
1.2,JDBC对象之DriverManage
JDBC访问数据库的步骤
定义(DriverManager:驱动管理器)
- 注册驱动:这可以让JDBC知道要使用的是哪个驱动。
- 获取Connection:如果可以获取到Connection,那么说明已经与数据库连接上了。
创建连接
- DriverManager负责驱动程序管理,数据库驱动则是为了应用程序服务的,所以DriverManager的重要任务就是提供连接的获取。
驱动程序查找
- DriverManager管理驱动程序,不仅仅提供了借助于驱动程序创建连接的能力,还能够返回给定的Driver或者Driver列表。
DriverManager常用方法
1.3,JDBC对象之Connection
定义
- Connection对象表示连接,与数据库的通讯都是通过这个对象展开的。
- Connection最为重要的一个方法就是用来获取Statement对象。
执行对象
执行对象有3种
- Statement:用于执行静态SQL语句并返回其生成的结果的对象。
- PreparedStatement:表示预编译的SQL语句的对象。
- CallableStatement:用于执行SQL存储过程的对象。
事务
- Connection提供了对于事务相关操作的支持。
重点方法简介
Statement |
createStatement() |
创建一个Statement对象,用于将SQL语句发送到数据库 |
PreparedStatement |
prepareStatement(String sql) |
创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库 |
- 存储过程执行对象创建CallableStatement
CallableStatement |
prepareCall(String sql) |
创建一个CallableStatement对象来调用数据库存储过程 |
1.4,JDBC对象之Statement
定义
- Statement是用来向数据库发送SQL语句的,这样数据库就会执行发送过来的SQL语句。
- void executeUpdate(String sql):执行更新操作(insert、update、delete等)
- ResultSet executeQuery(String sql):执行查询操作,数据库在执行查询后会把查询结果返回,查询结果就是ResultSet。
执行对象有3种
- Statement继承自Wrapper。
- PreparedStatement继承自Statement。
- CallableStatement继承自PreparedStatement。
继承关系图
区别与联系
- Statement接口:提供了执行语句和获取结果的基本方法。使用场景:普通的不带参数的查询SQL (带参数可能会造成SQL注入攻击)。
- PreparedStatement接口:添加了处理输入参数的方法。使用场景:支持可变参数的SQL。
- CallableStatement接口:添加了调用存储过程函数以及处理输出参数的方法。使用场景: 支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持。
- 这三种执行对象,都是为执行SQL而生,所以他们的重中之重全都是执行SQL。
1.5,JDBC对象之ResultSet
定义
- ResultSet对象表示查询结果集,只有在执行查询操作后才会有结果集的产生;结果集是一个二维的表格,有行有列,通过移动ResultSet结果集内部的"行光标",获取当前行上的每一列上的数据。
常用API方法
- boolean next():使"行光标"移动到下一行,并返回移动后的行是否存在。
- XXX getXXX(int col):获取当前行指定列上的值,参数就是列表,列数从1开始,而不是0。
ResultSet结果集的遍历方式
2,JDBC连接数据库
2.1,连接Oracle数据库
<dependencies>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6<artifactId>
<version>11.2.0.3</version>
</dependency>
</dependencies>
public class TestOracle
{
public static void main(String[] args) throws Exception
{
try
{
Class.forName("oracle.jdbc.driver.oracleDriver");
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
import java.sql.Connection;
import java.sql.DriverManager;
public class TestDriverManager
{
public static void main(String[] args) throws Exception
{
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
}
}
2.2,连接MySQL数据库
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47<version>
</dependency>
</dependencies>
public class TestMySQL
{
public static void main(String[] args) throws Exception
{
try
{
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
import java.sql.Connection;
import java.sql.DriverManager;
public class TestDriverManager
{
public static void main(String[] args) throws Exception
{
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "1234");
}
}
2.3,Statement接口和操作
Statement常用方法
Statement接口中的方法 |
描述 |
int executeUpdate(String sql) |
用于发送DML语句,增删改的操作:insert,update,delete;参数:SQL语句;返回值:返回对象数据库影响的行数 |
ResultSet executeQuery(String sql) |
用于发送DQL语句,执行查询的操作:select;参数:SQL语句;返回值:查询的结果集 |
void close() |
立即释放此Statement对象占用的数据库和JDBC资源。 |
JDBC使用Statement操作数据的步骤
- 1,使用Connection获取Statement对象
- 2,创建SQL语句
- 3,使用Statement对象执行SQL语句
- 4,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "1234");
Statement stmt = conn.createStatement();
String sql = "insert into dept values (10,'部门','城市')";
int i = stmt.executeUpdate(sql);
if (i > 0)
{
System.out.println("成功插入[" + i + "]条记录");
} else
{
System.out.println("插入失败");
}
stmt.close();
conn.close();
}
}
JDBC使用Statement查询数据的步骤
- 1,使用Connection获取Statement对象
- 2,创建SQL语句
- 3,使用Statement对象执行SQL语句
- 4,执行查询数据操作,得到ResultSet结果集对象
- 5,对结果集对象进行遍历,取出每一条记录
- 6,关闭连接,释放资源
import java.sql.*;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "1234");
Statement stmt = conn.createStatement();
String sql = "select * from dept ";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next())
{
System.out.println(rs.getInt(1) + "," +
rs.getString("dname") + "," + rs.getString(3));
}
rs.close();
stmt.close();
conn.close();
}
}
ResultSet常用方法
ResultSet接口中的方法 |
描述 |
boolean next() |
1,游标向下移动1行。2,返回boolean类型,如果还有下一条记录,返回true,否则返回false。 |
数据类型 getxxx() |
1,通过字段名获取数据,参数是String类型,返回不同的类型。2,通过列号获取数据,参数是整数,从1开始。返回不同的类型。 |
ResultSet接口获取结果集中字段数据的方法
|
|
|
boolean |
getBoolean(int columnIndex) |
检索该ResultSet对象的当前行中指定列的值为Java中的boolean |
boolean |
getBoolean(String columnLabel) |
检索该ResultSet对象的当前行中指定列的值为Java中的boolean |
byte |
getByte(int columnIndex) |
检索此ResultSet对象当前行中指定列的值为Java中的byte |
byte |
getByte(String columnLabel) |
以Java中的byte 此ResultSet对象的当前行中指定列的值 |
double |
getDouble(int columnIndex) |
以Java中的double 此ResultSet对象的当前行中指定列的值 |
double |
getDouble(String columnLabel) |
以Java中的double 此ResultSet对象的当前行中指定列的值 |
小结
ResultSet接口获取数据的注意事项
- 如果光标在第一行之前,使用rs.getxxx()获取列值,会报Before start of result set的错误。
- 如果光标在最后一行之前,使用rs.getxxx()获取列值,会报After end of result set的错误。
关闭连接,释放资源时需要注意的问题
- 需要释放的对象:ResultSet结果集、Statement语句、Connection连接。
- 释放原则:先关闭结果集ResultSet,再关闭Statement,最后关闭Connection。
- 代码位置:放在finally语句块中。
2.4,PreparedStatement接口和操作
为什么要使用PreparedStatement?
- 案例:用户登录(在控制台输入用户名和密码,如果和数据库中的数据匹配成功,则登录成功,否则登录失败)
- SQL注入问题(当我们输入以下密码,我们发现我们账号和密码都不对竟然登录成功了)
请输入用户名:
newboy
请输入密码:
a' or '1'='1
select * from user where name='newboy' and password='a' or '1'='1'
登录成功,欢迎你:newboy
产生SQL注入问题的原因
- 1,我们让用户输入的密码和SQL语句进行字符串拼接。用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义,以上问题称为SQL注入。
- 2,要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。
预编译对象解决SQL注入问题
- 1,使用占位符?来创建SQL语句,当创建预编译对象的时候,就提前把SQL语句发送到数据库保存(缓存),数据库获取到该SQL语句的结构,无法再修改。
- 2,执行查询的时候,发送的不是SQL语句,而是占位符的值。
定义
- PreparedStatement是Statement接口的子接口,继承于父接口中所有的方法,它是一个预编译的SQL语句。
PreparedStatement的作用和执行原理
PreparedStatement常用方法
Connection接口中的方法 |
描述 |
PreparedStatement preparedStatement(String sql) |
指定预编译的SQL语句,SQL语句中使用占位符?创建一个语句对象 |
PreparedStatement中设置的参数的方法 |
描述 |
void setDouble(int parameterIndex,double x) |
将指定参数设置为给定Java Double值 |
void setInt(int parameterIndex,int x) |
将指定参数设置为给定Java int值 |
void setLong(int parameterIndex,long x) |
将指定参数设置为给定Java long值 |
void setObject(int parameterIndex,Object x) |
使用给定对象设置指定参数的值 |
void setString(int parameterIndex,String x) |
将指定参数设置为给定Java String值 |
JDBC使用PreparedStatement查询数据的步骤
- 1,编写SQL语句,未知内容使用?占位
- 2,获得PreparedStatement对象
- 3,给占位符设置值
- 4,执行查询数据操作,得到ResultSet结果集对象
- 5,对结果集进行处理
- 6,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Test
{
public static void main(String[] args) throws Exception
{
String sql = "select * from hw_user where name = ? and password =?";
Connection connection = DriverManager.getConnection("");
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, username);
preparedStatement.setString(2, userpassword);
ResultSet resultSet = preparedStatement.executeQuery();
System.out.println("sql:" + sql);
if (resultSet.next())
{
System.out.println("登录成功");
} else
{
System.out.println("登录失败");
}
}
}
2.5,CallableStatement接口和操作
- CallableStatement和PreparedStatement一样也是Statement接口的子接口,其主要作用是调用存储过程。
CallableStatement的主要方法如下:
CallableStatement常用方法 |
描述 |
String getString(String parameterName) |
根据参数名称获取调用存储过程返回的值 |
String getString(int parameterIndex) |
根据编号获取调用存储过程返回的值 |
void setObject(String parameterName,Object x) |
给存储过程中的输入参数设置值 |
registerOutParameter(String parameterName,int sqlType) |
给存储过程中的输出参数设置值 |
execute() |
执行存储过程 |
JDBC使用CallableStatement调用存储过程操作数据的步骤:
- 1,创建callableStatement对象:CallableStatement call=connection.prepareCall("{call 存储过程名(?,?,?)}");
- 2,设置传入参数的值:call.set参数类型(int index,参数值);
- 3,设置传出参数的值:call.registerOutParameter(int index,Types.数据类型);
- 4,执行操作存储过程:call.execute();
- 5,得到返回的输出参数的值:call.getObject(参数序号);
JDBC使用CallableStatement调用存储过程完整示例
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Test
{
public static void main(String[] args) throws Exception
{
Connection connection = null;
CallableStatement callableStatement = null;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "1234");
callableStatement = connection.prepareCall("{call emp_pro(?,?,?)}");
callableStatement.setString(1, "CLERK");
callableStatement.setInt(2, 20);
callableStatement.registerOutParameter(3, OracleTypes.NUMBER);
callableStatement.execute();
System.out.println("员工个数为:" + callableStatement.getObject(3));
} catch (Exception e)
{
e.printStackTrace();
} finally
{
try
{
callableStatement.close();
connection.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
}
3,JDBC对数据库的增删改查
3.1,JDBC增删改查Oracle数据库
JDBC增删改查Oracle数据库(1)
使用JDBC向Oracle数据库中进行添加数据操作
案例:向部门表(Dept)添加一条记录
实现步骤
- 1,加载驱动程序
- 2,通过DriverManager获取Connection连接对象
- 3,创建SQL语句并且创建预编译对象
- 4,给占位符设置值
- 5,执行插入操作
- 6,关闭数据库连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("oracle.jdbc.Driver.OracleDriver");
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
PreparedStatement ps = connection.prepareStatement("insert into dept "
+ "values (seq_dept.nextval,?,?)");
ps.setString(1, "市场部");
ps.setString(2, "北京");
int i = ps.executeUpdate();
System.out.println("i=" + i);
ps.close();
connection.close();
}
}
JDBC增删改查Oracle数据库(2)
使用JDBC对Oracle数据库进行修改数据操作
案例:操作员工表(Emp),把员工"ALLEN"的工资上调500,奖金上调100.
实现步骤:
- 1,加载驱动程序
- 2,通过DriverManager获取Connection连接对象
- 3,创建SQL语句并且创建预编译对象
- 4,给占位符设置值
- 5,执行修改操作
- 6,关闭数据库连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
PreparedStatement ps = connection.prepareStatement("update emp set sal= = sal + ?,"
+ "comm = comm + ? where ename = ?");
ps.setDouble(1, 500);
ps.setDouble(2, 100);
ps.setString(3, "ALLEN");
int i = ps.executeUpdate();
System.out.println("i: " + i);
ps.close();
connection.close();
}
}
JDBC增删改查Oracle数据库(3)
使用JDBC对Oracle数据库进行删除数据操作
案例:操作员工表(Emp),把编号为"7934"的员工删除
实现步骤:
- 1,加载驱动程序
- 2,通过DriverManager获取Connection连接对象
- 3,创建SQL语句并且创建预编译对象
- 4,给占位符设置值
- 5,执行修改操作
- 6,关闭数据库连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
PreparedStatement ps = connection.prepareStatement("delete from emp where enmpno = ?");
ps.setInt(1, 7934);
int i = ps.executeUpdate();
System.out.println("i: " + i);
ps.close();
connection.close();
}
}
JDBC增删改查Oracle数据库(4)
使用JDBC对Oracle数据库进行查询数据操作
案例:操作员工表(Emp),根据员工姓名(模糊查询),职位,入职时间,所属部门查询员工信息。
实现步骤:
- 1,加载驱动程序
- 2,通过DriverManager获取Connection连接对象
- 3,创建SQL语句并且创建预编译对象
- 4,给占位符设置值
- 5,执行修改操作
- 6,关闭数据库连接,释放资源
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.*;
public class Test1
{
public static void main(String[] args) throws Exception
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn1 = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
PreparedStatement ps1 = conn1.prepareStatement("select * from emp where ename like ? "
+ "and job = ? and hiredate >= ? and deptno = ?");
ps1.setString(1, "%d%");
ps1.setString(2, "CLERK");
ps1.setDate(3, Date.valueOf("2021-12-03"));
ps1.setInt(4, 20);
ResultSet rs = ps1.executeQuery();
while (rs.next())
{
System.out.println(rs.getInt(1) + " - " + rs.getString(2) + " - " + rs.getString(3));
}
rs.close();
ps1.close();
conn1.close();
}
}
3.2,JDBC增删改查MySQL数据库
JDBC增删改查MySQL数据库(1)
使用JDBC向MySQL数据库中进行添加数据操作
案例:向图书表(book_info)添加一条记录
实现步骤:
- 1,获取数据库连接对象
- 2,创建SQL语句并且创建预编译的对象
- 3,给占位符设置值
- 4,执行插入操作
- 5,关闭连接,释放资源
import java.sql.*;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
PreparedStatement ps = conn.prepareStatement("insert into book_info values (null,?,?,?,?,?,?,?)");
ps.setString(1, "GBK_005");
ps.setString(2, "Thinking in Java");
ps.setInt(3, 8);
ps.setString(4, "埃克尔");
ps.setString(5, "机械工业出版社");
ps.setDate(6, Date.valueOf("2021-12-03"));
ps.setInt(7, 1);
int i = ps.executeUpdate();
ps.close();
conn.close();
System.out.println("i: " + i);
}
}
JDBC增删改查MySQL数据库(2)
MySQL数据库和Oracle数据库插入数据的去比:
JDBC增删改查MySQL数据库(3)
使用JDBC对MySQL数据库进行修改数据操作
案例:操作图书表(book_info),把图书编号为"GBK_001"的图书的出版社修改为"少年儿童出版社"
实现步骤:
- 1,获取数据库连接对象
- 2,创建SQL语句并且创建预编译对象
- 3,给占位符赋值
- 4,执行修改操作
- 5,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
PreparedStatement ps = conn.prepareStatement("update book_info set publish_press = ? where book_code = ?");
ps.setString(1, "少年儿童出版社");
ps.setString(2, "GBK_001");
int i = ps.executeUpdate();
ps.close();
conn.close();
System.out.println("i: " + i);
}
}
JDBC增删改查MySQL数据库(4)
使用JDBC对MySQL数据库进行删除数据操作
案例:操作图书表(book_info),删除图书编号为"YS_001"的图书信息
实现步骤:
- 1,获取数据库连接对象
- 2,创建SQL语句并且创建预编译对象
- 3,给占位符设置值
- 4,执行删除操作
- 5,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
PreparedStatement ps = conn.prepareStatement("delete from book_info where book_code = ?");
ps.setString(1, "YS_001");
int i = ps.executeUpdate();
ps.close();
conn.close();
System.out.println("i: " + i);
}
}
JDBC增删改查MySQL数据库(5)
使用JDBC对MySQL数据库进行查询数据操作
案例:操作图书表(book_info),查询"人民教育出版社"出版的图书信息,并且显示图书的类型名称。
分析:图书表(book_info)和图书分类表(book_type)需要做关联查询
实现步骤:
- 1,获取数据库连接对象
- 2,创建SQL语句并且创建预编译对象
- 3,给占位符设置值
- 4,执行查询操作
- 5,遍历结果集,输出图书信息
- 6,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Test
{
public static void main(String[] args) throws Exception
{
Class.forName("com.mysql.jdbc.Drvier");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
String sql = "select b.*,t.`type_name` " +
"from book_info b " +
"inner join book_type t on b.`book_type` = t.`id` " +
"where b.`publish_press` = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "人民教育出版社");
ResultSet rs = ps.executeQuery();
while (rs.next())
{
System.out.println(rs.getInt(1) + "," + rs.getString(2) + "," + rs.getString(3) + "," + rs.getString("type_name"));
}
rs.close();
ps.close();
conn.close();
}
}
JDBC增删改查MySQL数据库(6)
使用JDBC向MySQL数据库中进行批量插入数据操作
- Java的批量操作机制允许多条语句一次性提交给数据库批量处理,通常情况下比单独提交处理更有效率。
JDBC的批量处理语句包括下面三个方法
PreparedStatement的方法名 |
内容概述 |
void addBatch() |
向这个PreparedStatement对象的一批命令添加一组参数。 |
Statement的方法名 |
内容概述 |
void clearBatch() |
清空这个Statement对象当前的SQL命令列表。 |
int[] executeBatch() |
将一批命令提交到数据库以执行,并且所有命令都执行成功,返回一个更新计数的数组。 |
案例:使用JDBC向MySQL的customers数据表中插入10万条记录,测试如何插入用时最短。
实现步骤:
- 1,使用PreparedStatement的非批量操作方式,测试插入时间。
- 2,使用Batch批量操作,测试插入时间。
总结:
- 通过对比插入数据程序耗费的时间,发现使用Batch批量操作,提高了插入数据的效率。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Date;
public class Test
{
Connection conn = null;
PreparedStatement ps = null;
public static void main(String[] args) throws Exception
{
Class.forName("com.mysql.jdbc.Drvier");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
conn.setAutoCommit(false);
ps = conn.prepareStatement("insert into customers values (?,?,?)");
Date date = new Date(date.getTime());
long begin = System.currentTimeMillis();
for (int i = 1; i < 100009; i++)
{
ps.setInt(1, i);
ps.setString(2, "name_" + i);
ps.setDate(3, date);
ps.addBatch();
if (i % 300 == 0)
{
ps.executeBatch();
ps.clearBatch();
}
}
if (100009 % 300 != 0)
{
ps.executeBatch();
ps.clearBatch();
}
long end = System.currentTimeMillis();
System.out.println("Time: " + (end - begin));
conn.commit();
}
}
3.3,JDBC使用数组封装自定义操作工具类
JDBC使用数组封装自定义操作工具类(1)
创建JDBCUtils数据库连接工具类
什么是工具类?
- 如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。
实现步骤:
- 1,把用户名、密码、URL、驱动类定义成静态变量。
- 2,通过静态代码块加载数据库驱动
- 3,创建获取数据库连接的方法
- 4,创建关闭连接,释放资源的方法(可以使用方法的重载)
JDBC使用数组封装自定义操作工具类(2)
工具类JDBCUtils的核心代码(1)
import java.sql.*;
public class Test
{
private static String className = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8";
private static String username = "root";
private static String password = "1234";
static
{
try
{
Class.forName(className);
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
public static Connection getConn()
{
try
{
return DriverManager.getConnection(url, username, password);
} catch (SQLException e)
{
e.printStackTrace();
throw new RuntimeException("数据库连接错误");
}
}
}
JDBC使用数组封装自定义操作工具类(3)
工具类JDBCUtils的核心代码(2)
public class Test
{
private static String className = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8";
private static String username = "root";
private static String password = "1234";
public static void closeAll(Connection conn, Statement stmt, ResultSet rs)
{
if (rs != null)
{
try
{
rs.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
if (stmt != null)
{
try
{
stmt.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
public static void closeAll(Connection conn, Statement stmt)
{
if (stmt != null)
{
try
{
stmt.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
public static void closeAll(Connection conn)
{
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
}
JDBC使用数组封装自定义操作工具类(4)
使用DAO工具类来封装增删改查的操作
什么是DAO模式?
- DAO(Data Access Object数据存取对象)是指位于业务逻辑和持久化数据之间实现对持久化数据的访问。通俗来讲,就是将数据库操作封装起来。
一个典型的DAO模式主要由以下几部分组成
- DAO接口:把对数据库的所有操作定义成抽象方法,可以提供多种实现。
- DAO实现类:针对不同数据库给出DAO接口定义方法的具体实现。
- 实体类:用于存放与传输对象数据
实现步骤:
- 1,创建包名:DAO
- 2,创建CRUD的工具类接口:实体类名+Dao
- 3,在接口中定义CRUD的抽象方法
- 4,创建CRUD的工具类实现类:实体类名+Dao+Impl
JDBC使用数组封装自定义操作工具类(5)
案例:使用工具类来封装图书表(BookInfo),进行增删改查的操作
实现步骤:
public interface BookInterface
{
int addBookInfo(BookInfo bookInfo) throws Exception;
int updateBookInfo(String bookCode, String publishPress) throws Exception;
int deleteBookInfo(String bookCode) throws Exception;
BookInfo[] getBookInfo(String publishPress) throws Exception;
}
public class BookInfoDaoImpl implements BookInfoDao
{
public int addBookInfo(BookInfo bookInfo) throws Exception;
public int updateBookInfo(String bookCode, String publishPress) throws Exception;
public int deleteBookInfo(String bookCode) throws Exception;
public BookInfo[] getBookInfo(String publishPress) throws Exception;
}
JDBC使用数组封装自定义操作工具类(6)
- 把增删改查的代码,可以提取到JDBCUtils中,对参数使用数组进行封装,代码更简洁。
- JDBCUtils工具类优化增删改核心代码:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test
{
public static int executeUpdate(String preparedSql, Object[] param) throws ClassNotFoundException
{
Connection conn = null;
PreparedStatement pstmt = null;
int count = 0;
try
{
conn = pstmt.getConnection();
pstmt = conn.prepareStatement(preparedSql);
if (param != null)
{
for (int i = 0; i < param.length; i++)
{
pstmt.setObject(i + 1, param[i]);
}
}
count = pstmt.executeUpdate();
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
pstmt.close();
conn.close();
}
return count;
}
}
3.4,面向对象继承和重写实现多数据库操作
面向对象继承和重写实现多数据库操作实现步骤
public abstract class BaseDao
{
public abstract Object[] queryEmpByCondition(Emp emp) throws Exception;
public abstract int updateEmpById(Integer empno, Double sal) throws Exception;
public abstract int delEmpById(Integer empno) throws Exception;
public abstract int insertEmp(Emp emp) throws Exception;
}
public class MySqlDaoImpl extends BaseDao
{
}
public class OracleDaoImpl extends BaseDao
{
}
评论(0)