JDBC工作原理图
- 第一步:注册驱动程序
- Class.forName("驱动类的全名")
- 第二步: 请求连接
- Connection conn = DriverManager.getConnection(String url,String user,String passwd)
- 第三步: 获取执行sql语句的对象,发送给DBMS
- Statement stat = conn.createStatement();
- 第四步:返回结果集,程序员进行处理
- ResultSet rs =stat.executeQuery("select * from emp")
- 第五步: 关闭连接操作
- rs.close();
- stat.close();
- conn.close();
JDBC中常用的接口和类
java.sql.DriverManager:类,用于连接数据库,返回Connection对象
- DriverManager.getConnection(String url, String user, String password)
- url: 连接指定数据库的地址 jdbc:mysql://ip:port/dbname
jdbc:mysql://localhost:3306/mydb
- jdbc: 这是jdbc这套接口的规范协议
- mysql: 表明jdbc要连接mysql数据库
- localhost: 数据库服务端所在的主机的IP地址 纯数字的ip:127.0.0.1用来表示本地,localhost也用来表示本地
也可以使用路由器分配的真实IP- 3306:这个是mysql数据库的默认端口号
- mydb: mysql数据库里的一个库名
扩展:如果想链接oracle数据库
jdbc:oracle:thin:@ip:port:pid
举例说明:jdbc:oracle:thin:@localhost:1521:orcl
- user: 连接用户名
- password:密码
java.sql.Connection:接口
Statement createStatement();
作用:用于获取Statement对象
java.sql.Statement:接口
execute(String sql):通常用于DDL
executeUpdate(String sql):通常用于DML
executeQuery(String sql):用于DQL
java.sql.ResultSet:接口,其子类型封装了DQL的返回值
next():光标方法,向下移动一行
getDate(int columnIndex)
getDate(String columnLabel)
getString(int columnIndex)
getString(String columnLabel)
getInt(int columnIndex)
getInt(String columnLabel)
getDouble(int columnIndex)
getDouble(String columnLabel)
示例
jar包网盘地址:https://pan.baidu.com/s/1oY8hwOBn8sJ8RWfMTWpGQQ 提取码:63fx
下载完成后,创建lib目录,放入mysql的驱动包,右键点击jar文件,选择Add as library
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class day01 {
public static void main(String[] args) {
//practice1();
//practice2();
//practice3();
practice4();
}
// JDBC入门第一个案例,删除操作
public static void practice1(){
Connection connection=null;
Statement statement=null;
try {
//第一步利用反射机制获取mysql的驱动器类型到内存中
Class.forName("com.mysql.jdbc.Driver");
//第二步获取连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "2333");
//第三步获取执行对象Statement
statement = connection.createStatement();
//第四步,发送sql语句
String sql="delete from emp where empno=9001";
int nub = statement.executeUpdate(sql);
System.out.println("受影响的条数:"+nub);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//使用DBUtil进行删除操作
public static void practice2(){
Connection connection = null;
Statement statement=null;
try{
//建立连接,获取连接对象
connection= DBUtil.getConnection();
//获取执行对象
statement = connection.createStatement();
String sql="delete from emp where empno=9001";
int nub=statement.executeUpdate(sql);
System.out.println("受影响的条数:"+nub);
}catch (Exception e){
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,null);
}
}
//查询
public static void practice3(){
Connection conn=null;
Statement statement=null;
ResultSet resultSet=null;
try{
//利用反射将mysql的驱动器类com.mysql.jdbc.Driver加载到内存中
Class.forName("com.mysql.jdbc.Driver");
//建立连接
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","2333");
//获取执行对象
statement = conn.createStatement();
String sql="select * from emp where empno=9999";
resultSet = statement.executeQuery(sql);
if(resultSet.next()){
int empno=resultSet.getInt(1);
String ename=resultSet.getString("ename");
String job=resultSet.getString("job");
int mgr=resultSet.getInt("mgr");
Date hiredate=resultSet.getDate("hiredate");
double sal=resultSet.getDouble("sal");
double comm=resultSet.getDouble("comm");
int deptno=resultSet.getInt("deptno");
System.out.println(empno+"\t"+ename+"\t"+job+"\t"+mgr+"\t"+hiredate+"\t"+sal+"\t"+comm+"\t"+deptno);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
resultSet.close();
statement.close();
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
//使用DBUtil查询
public static void practice4(){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//建立连接
connection= DBUtil.getConnection();
//获取执行对象
statement = connection.createStatement();
//编写sql语句
String sql="select * from emp where empno=9999";
//执行sql并返回结果集
resultSet = statement.executeQuery(sql);
if(resultSet.next()){
int empno = resultSet.getInt(1);
String ename = resultSet.getString("ename");
String job = resultSet.getString(3);
int mgr = resultSet.getInt("mgr");
Date hiredate = resultSet.getDate(5); //java.sql.Date
double sal = resultSet.getDouble(6);
double comm = resultSet.getDouble(7);
int deptno = resultSet.getInt(8);
System.out.println(empno+"\t"+ename+"\t"+job+"\t"+mgr+"\t"+hiredate+"\t"+sal+"\t"+comm+"\t"+deptno);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
}
}
class DBUtil{
//添加静态属性
private static String driverclass;
private static String url;
private static String user;
private static String password;
//添加静态代码块,
// 用于加载静态资源(图片文件,音频,视频,html,css,第三方jar包)
//只在加载.class文件时执行一次
//加载properties文件
static{
try{
//获取IO流,读取配置文件中的参数信息
//这个配置文件必须放置在src下
//类加载器里的getResourceAsStream(String path);
//此方法的参数是一个文件的路径,此路径是相对于项目的src来说的,
//因此写相对路径时,如果直接写文件名,那么此文件必须在src下
InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
//获取Properties对象
Properties properties=new Properties();
//加载数据
properties.load(in);
driverclass=properties.getProperty("driverclass");
url=properties.getProperty("url");
user=properties.getProperty("user");
password=properties.getProperty("password");
//注册驱动
Class.forName(driverclass);
//关闭流
in.close();
}catch (Exception e) {
e.printStackTrace();
}
}
//获取连接对象
public static Connection getConnection(){
try {
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//关闭连接
public static void close(Connection connection, Statement statement, ResultSet resultSet){
try{
if(resultSet!=null){
resultSet.close();
}
if(statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
db.properties文件
注:这个文件一定要反正src目录下,否则会报以下异常
jdbc的批处理
每一次的sql操作都会占用数据库的资源。如果将N条操作先存储到缓存区中,然后再一次性刷到数据库中,这 就减少了与数据库的交互次数。因此可以提高效率。
- Statement中的两个批处理方法:
- addBatch(String sql):将sql语句添加到缓存中
- executeBatch():将缓存中的sql一次性刷到数据库中
Junit测试工具类
此工具类的用途是进行测试,比较方便。
它使用了注解的方式,在一个非静态方法上写注解@Test,就可以运行这个方法。
另外两个常用的注解
@Before: 位置也是在方法上使用,特点是对应的方法在@Test注解下的方法执行前执行。
@After: 位置也是在方法上使用,特点是对应的方法在@Test注解下的方法执行后执行。
注意:需要引用两个jar包 junit-4.12.jar 和 hamcrest-core-1.3.jar
网盘地址:https://pan.baidu.com/s/1oY8hwOBn8sJ8RWfMTWpGQQ 提取码:63fx
使用Junit和DBUtil来完成emp表的增删改查等操作
public class Test{
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
@Before
public void execBefore(){
conn = DBUtil.getConnection();
}
@After
public void execAfter(){
DBUtil.closeConnection(conn,stat,rs);
}
@Test
public void queryAll(){
try{
stat = conn.createStatement();
rs = stat.executeQuery("select * from emp");
//注意:此时,rs里封装的应该是多行记录。因此游标有一行一行的下移
while(rs.next()){
int empno = rs.getInt(1);
String ename = rs.getString("ename");
String job = rs.getString(3);
int mgr = rs.getInt("mgr");
Date hiredate = rs.getDate(5); //java.sql.Date
double sal = rs.getDouble(6);
double comm = rs.getDouble(7);
int deptno = rs.getInt(8);
System.out.println(empno+"\t"+ename+"\t"+job+"\t"+mgr+"\t"+hiredate+"\t"+sal+"\t"+comm+"\t"+deptno);
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void queryOne(){
try{
Statement statement = conn.createStatement();
String sql="select ename from emp where empno=7499";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("ename"));
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void addOne(){
try{
Statement statement = conn.createStatement();
//7499 ALLEN SALESMAN 7698 1981-02-20 1600 300 30
//insert into emp values(9999,'hhh','SALESMAN',7499,2020-5-18,1500,300,3)
String sql="insert into emp values(9999,'hhh','SALESMAN',7499,'2020-5-18',1500,300,30)";
int i = statement.executeUpdate(sql);
System.out.println("有"+i+"行受到影响");
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void delOne(){
try{
Statement statement = conn.createStatement();
String sql="delete from emp where empno=9999";
int i = statement.executeUpdate(sql);
System.out.println("有"+i+"行受到影响");
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void modifyOne(){
try{
Statement statement = conn.createStatement();
String sql="update emp set ename='ddddd' where empno=9999";
int i = statement.executeUpdate(sql);
System.out.println("有"+i+"行受到影响");
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 研究一下Statement类型的批量操作
* 想向数据库nz202下的testbatch表中插入10w记录中
*
* 原理:批量插入数据时,可以减少与数据库的交互次数,从而提高性能,减少时间。
*/
@Test
public void testBatch(){
try{
//给stat赋值
stat = conn.createStatement();
for (int i = 0; i < 100001; i++) {
int num = (int)(Math.random()*2);
String gender = null;
if(num==0){
gender = "f";
}else {
gender = "m";
}
String sql = "insert into testbatch values (null,'zs"+i+"','"+gender+"')";
/**
* void addBatch(String sql): 将sql字符串添加到缓存中。
*/
stat.addBatch(sql);
/**
* 每1000条一刷新缓存
*
* executeBatch() :刷新缓存
*/
if(i%1000==0){
stat.executeBatch();
}
}
//for循环结束后,缓存里可能还有数据啊
stat.executeBatch();
}catch (Exception e){
e.printStackTrace();
}
}
}