JavaWeb之 JDBC详解&&JDBC管理事务

JDBC详解&&JDBC管理事务

一、JDBC

1)概念:Java DataBase Connectivity (Java数据库连接),即用Java语言操作数据库

2)JDBC的本质:其实是官方(SUN公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类,即使用的是接口,执行的是实现类

如:

Person接口		Worker类		Person p = new Worker();	p.eat();

二、快速入门

1)步骤:

①导入驱动jar包
②注册驱动
③获取数据库连接对象Connection
④定义sql
⑤获取执行sql语句的对象 Statement
⑥执行sql,接收返回结果
⑦处理结果
⑧释放资源

范例:

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.Statement;

/*
    JDBC快速入门
*/
public class JdbcDemo1 {
    public static void main(String[] args) throws Exception {
//            ①导入驱动jar包,连接什么样的数据库,就导入对应的jar包
//              复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下,Add As Library

//            ②注册驱动
                Class.forName("com.mysql.jdbc.Driver");
//            ③获取数据库连接对象Connection
                Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/studytest", "root", "root");
//            ④定义sql
                String sql = "update account set  balance = 1000 where id = 1";
//            ⑤获取执行sql语句的对象 Statement
                Statement stmt = conn.createStatement();
//            ⑥执行sql,接收返回结果
                int count = stmt.executeUpdate(sql);
//            ⑦处理结果
                System.out.println(count);
//            ⑧释放资源
                stmt.close();
                conn.close();

    }
}

三、对JDBC中各个接口和类详解

1)DriverManager:驱动管理对象

功能:

①注册驱动:告诉程序该用哪一个数据库驱动jar

static void registerDriver(Driver driver) //注册与给定的驱动程序:DriverManager

代码演示:

Class.forName("com.mysql.jdbc.Driver");
/* com.mysql.jdbc.Driver
类中有一个静态方法可以来注册DriverManager*/
		

注意:mysql5之后的驱动jar包可以省略注册驱动的步骤

②获取数据库连接

static Connection getConnection(String url,String user,String password)

参数:url:指定的路径、user用户名、password密码

Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/studytest", "root", "root"); 
/*jbdc:mysql://ip地址(域名)//数据库名,
如果连接的是本机mysql服务器,
并且mysql服务默认端口是3306,
则url可简写为:
jdbc:mysql:///数据库名*/

2)Connection:数据库连接对象

功能:
① 获取执行sql对象

Statement createStatement()
PreparedStatement prepareStatement(String sql)

② 管理事务:

开启事务:void setAutoCommit(boolean autoCommit)//调用该方法设置参数为false,即开启事务
提交事务:void commit()
回滚事务:void rollback()

3)Statement:执行sql的对象

boolean execute(String sql) 
//可以执行任意的sql

int executeUpdate(String sql) 
/*执行DML语句、DDL语句,
返回值是影响的行数,
可以通过影响的行数判断语句是否执行成功,
返回值大于零则成功,反之失败。*/

ResultSet executeQuery(String sql)
//执行DQL(SELECT)语句

4)ResultSet:结果集对象,封装查询结果

next():游标向下移动一行
getXxx(参数):获取数据,Xxx代表数据类型,如getInt()

参数:

Int代表列的编号,从1开始,如getString(1)

String代表列的名称,如getString(“name”)

范例:

package JdbcDemo;

import java.sql.*;

public class StatementPractice {
    public static void main(String[] args) throws Exception {
        Statement stmt =null;
        Connection conn = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");

            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/studytest", "root", "root");

            stmt = conn.createStatement();

            String sql = "SELECT * FROM account";

            rs = stmt.executeQuery(sql);

            rs.next(); // 游标向下移动一行

            int id = rs.getInt(1);
            String name = rs.getString("name");
            double balance = rs.getDouble("balance");

            System.out.println(id+"---"+name+"---"+balance);


        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (rs!=null)
                rs.close();//最后创建最先释放
            if (stmt!=null)
                stmt.close();//避免空指针异常
            if (conn!=null)
                conn.close();
        }
    }
}

遍历结果集:

游标向下移动一行时,先判断是否有数据,再获取数据

next():游标向下移动一行,判断还有没有下一行,如果没有则返回false,如果有则返回true

范例:

while(rs.next()) { // 游标向下移动一行

                int id = rs.getInt("id");
                String name = rs.getString("name");
                double balance = rs.getDouble("balance");

                System.out.println(id + "---" + name + "---" + balance);

            }

5)PreparedStatement:执行sql的对象,功能更加强大

SQL注入问题:在拼接SQL时,有一些SQL的特殊关键字参与字符串的拼接,会造成安全性问题
解决SQL注入问题:使用PreparedStatement对象来解决,PreparedStatement是一种预编译的SQL,即定义的SQL语句参数使用?作为占位符

方法:Connection. prepareStatement(String sql)

给?赋值:

如:SELECT * FROM emp WHERE id = ? AND name = ?;

方法:setXxx(参数1,参数2); //参数1表示第几个?,参数2表示?代表的值

注意:一般都会使用PreparedStatement来完成增删改查的所有操作,因为其可以防止SQL注入且效率更高

6)Statement练习:

注册驱动Class.forName——创建Connection——创建Statement——写sql——获得结果、处理结果

//account表添加一条记录

package JdbcDemo;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.Statement;

public class StatementPractice {
    public static void main(String[] args) throws Exception {
        Statement stmt =null;
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");

            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/studytest", "root", "root");

            stmt = conn.createStatement();

            String sql = "INSERT INTO account values(null,'王五',3000)";

            int count = stmt.executeUpdate(sql);

            System.out.println(count);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (stmt!=null)
                stmt.close();//避免空指针异常
            if (conn!=null)
                conn.close();
        }
    }
}

7)SELECT练习:定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回

范例:

package JdbcDemo;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class empPractice {
    public static void main(String[] args) throws SQLException {
        List<Emp> list = new empPractice().findAll();
        System.out.println(list);//打印的时emp的重写的toString方法
    }
    public List<Emp> findAll() throws SQLException {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        List<Emp> list = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///studytest","root","root");
            stmt = conn.createStatement();
            String sql = "SELECT * FROM emp";
            rs = stmt.executeQuery(sql);

            Emp emp = null;
            list  = new ArrayList<Emp>();

            while (rs.next()) {
                int id = rs.getInt("id");
                String ename = rs.getString("ename");
                int job_id = rs.getInt("job_id");
                int mgr = rs.getInt("mgr");
                Date joindate = rs.getDate("joindate");
                double salary = rs.getDouble("salary");
                double bonus = rs.getDouble("bonus");
                int dept_id = rs.getInt("dept_id");
                emp = new Emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id);
                list.add(emp);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            if (rs != null)
                rs.close();
            if (stmt != null)
                stmt.close();
            if (conn != null)
                conn.close();
        }
        return list;
    }
}

8)抽取JDBC工具类:JDBCUtils

范例:

package Util;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    /*
    * 文件的读取,只需读取一次即可拿到这些值。使用静态代码块
    * */
    static {
        //读取资源文件,获取值
        Properties pro = new Properties();
        //获取src路径下的文件的方式-->ClassLoader 类加载器
        ClassLoader classLoader = JDBCUtils.class.getClassLoader();
        URL res = classLoader.getResource("jdbc.properties");
        String path = res.getPath();
        try {
            pro.load(new FileReader(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        url = pro.getProperty("url");
        user = pro.getProperty("user");
        password = pro.getProperty("password");
        driver = pro.getProperty("driver");
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /*
    * 获取连接
    * @return 连接对象
    * */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }

    public static void close(Statement stmt,Connection conn){
        if (stmt!=null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn!=null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    public static void close(Statement stmt, Connection conn, ResultSet rs){
        if (stmt!=null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn!=null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (rs!=null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

目的:简化书写,不用为了简单的查询目标而书写过多重复的创建对象语句

1.抽取注册驱动

2.抽取一个方法获取连接对象:需求:不想传递参数,还得保证工具类的通用性——解决方案:配置文件

范例:

url=jdbc:mysql:///studytest
user=root
password=root
driver=com.mysql.jdbc.Driver

3.抽取一个方法释放资源:方法重载

9)JDBC控制事务:

事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败

使用Connection对象来管理事务:
开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务
提交事务:commmit()
回滚事务:rollback()

案例:事务实现转账问题,account表中有张三李四分别拥有1000元,实现张三转给李四500元

范例:

package JdbcDemo;

import Util.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

/*
* 事务操作
* */
public class AccountCommitDemo {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        try {
            //获取连接
            conn = JDBCUtils.getConnection();
            //开启事务
            conn.setAutoCommit(false);
            //定义SQL
            String sql1 = "Update account set balance = balance - ? where id  = ?";
            String sql2 = "Update account set balance = balance + ? where id  = ?";
            //获取sql对象
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //设置参数
            pstmt1.setDouble(1,500);
            pstmt1.setInt(2,1);
            pstmt2.setDouble(1,500);
            pstmt2.setInt(2,2);

            pstmt1.executeUpdate();
            pstmt2.executeUpdate();

            //没有问题则提交事务
            conn.commit();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            //出现异常时回滚事务
            if (conn!=null){
                try {
                    conn.rollback();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        finally {
            JDBCUtils.close(pstmt1,conn);
            JDBCUtils.close(pstmt2,null);
        }
    }
}

版权声明:本文为m0_46421964原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>