JavaDataBase Connectivity Java 数据库连接,操作数据库

操作步骤

1.导入驱动jar包

  • 复制jar包到项目的libs目录下
  • 右键该目录->Add as Library

2.注册驱动
Class.forName(“com.mysql.cj.jdbc.Driver”);
3.获取数据库连接对象
Connection conn = DriverManager.getConnection(url,user,password);
4.定义sql语句
String sql=”xxx”;
5.获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
6.执行sql
int count = stmt.executeUpdate(sql);
7.处理结果
System.out.println(count);
8.释放资源
stmt.close();
conn.close();

  1. import java.sql.Connection;
  2. import java.sql.DriverManager;
  3. import java.sql.Statement;
  4. public class Demo01 {
  5. public static void main(String[] args) throws Exception {
  6. //2-注册驱动
  7. Class.forName("com.mysql.cj.jdbc.Driver");
  8. //3-获取数据库连接对象
  9. Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaSQL", "root", "********");
  10. //4-定义sql语句
  11. String sql="update account set balance = 123 where id=1";
  12. //5-获取执行sql的对象 Statement
  13. Statement stmt = conn.createStatement();
  14. //6-执行sql
  15. int count = stmt.executeUpdate(sql);
  16. //7-处理结果
  17. System.out.println(count);
  18. //8-释放资源
  19. stmt.close();
  20. conn.close();
  21. }
  22. }

对象

  • DriverManager : 驱动管理对象
  • Connection : 数据库连接对象
  • Statement : 执行sql的对象
  • ResultSet : 结果集对象
  • PreparedStatement : 执行sql的对象

    DriverManager

    功能
    1.注册驱动:告诉程序该使用哪一个数据库驱动jar
    static void registerDriver(Driver driver) : 注册与给定的驱动程序 DriverManager
    写代码使用: Class.froName("com.mysql.jdbc.Driver");
    查看 com.mysql.jdbc.Driver 的源码发现静态代码块
    registerDriver就在该代码块中
    1. static {
    2. try {
    3. DriverManager.registerDriver(new Driver());
    4. } catch (SQLException var1) {
    5. throw new RuntimeException("Can't register driver!");
    6. }
    7. }

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

2.获取数据库连接
方法: static Connection getConnevtion(String url, String user, String password)
参数:
url : 指定连接的路径
格式(语法): jdbc:mysql://ip地址(域名):端口号/数据库名称
例子:jdbc:mysql://localhost:3306/javaSQL
user : 用户名
password :密码

Connection

1.功能:

  • 获取执行sql的对象

Statement createStatement()
PreparedStatement prepareStatement(String sql)

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

Statement 🌟🌟

用于执行静态SQL语句并返回其生成的结果的对象

不同语句的方法

boolean execute(String sql) : 执行任意sql (不常用)
int executeUpdate(String sql) : 执行DML(insert,update,delete)语句,DDL(表和库的 create,alter,drop)语句(DDL语句不常用)

  • 返回值:实际影响的行数 -> 可以通过行数判断DML是否执行成功( >0成功,否则失败)

ResultSet executeQuery(String sql) : 执行DQL(select)语句 🌟

ResultSet结果集

封装查询结果
方法:
next() : 游标向下移动一行
getXxx(参数) : 获取数据-(Xxx代表数据类型)
参数:1.Int - 代表列编号(从1开始) 2.String - 代表列的名称
如:int getInt(1) , String getString(“name”)
注意
使用步骤:

  • 游标向下移动一行
  • 判断是否有数据
  • 获取数据 ```java //3

    1. String sql="select * from account";
    2. //4
    3. stmt = conn.createStatement();
    4. //5
    5. rs = stmt.executeQuery(sql);
    6. //6
    7. //游标向下移动
    8. while(rs.next()){
    9. //循环判断游标是否是最后一行末尾
    10. //获取数据
    11. int id = rs.getInt(1);
    12. String name = rs.getString("name");
    13. double balance = rs.getDouble(3);
    14. System.out.println(id +"---"+name+"---" +balance);
    15. }

//注意关闭ResultSet对象资源 if(rs!=null){ try { rs.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } }

  1. <a name="aAvzz"></a>
  2. #### PreparedStatement
  3. 执行sql的对象<br />**1.SQL注入问题:**<br />1.输入错误的用户名和密码,但是密码为: a' or 'a' = 'a<br />那么判断用户名和密码的sql语句就变成了"select * from user where username = 'xxx' and password = 'a' or 'a' = 'a' "<br />成为了恒等式,则可以直接登陆成功<br />**2.结果SQL注入问题:**<br />使用PreparedStatement对象<br />预编译的SQL:参数使用?作为占位符<br />步骤:<br />1.导入jar包<br />2.注册驱动<br />3.获取数据库连接对象Connection<br />4.定义sql<br />注意:sql参数使用?作为占位符,如:select * from user where username = ? and password = ?<br />5.获取执行sql语句的对象 PreparedStatement<br />Connection.prepareStatement(String sql) 这里提前传递sql语句<br />6.给?赋值
  4. - 方法:setXxx(参数1,参数2):
  5. - 参数1为?位置,参数2为?的值
  6. 7.执行sql,接收返回结果<br />不需要传递sql语句<br />8.处理结果<br />9.释放资源<br />**注意:后期都会使用PreparedStatement来完成增删改查的所有操作**
  7. <a name="6xWbF"></a>
  8. ### 例子
  9. <a name="7xPXQ"></a>
  10. #### insert语句
  11. 标准格式代码写法**(try..catch..finally)**
  12. ```java
  13. import java.sql.Connection;
  14. import java.sql.DriverManager;
  15. import java.sql.SQLException;
  16. import java.sql.Statement;
  17. public class DMLtest {
  18. public static void main(String[] args) {
  19. //提前创建对象方便finally关闭资源
  20. Statement stmt= null;
  21. Connection conn =null;
  22. //1.注册驱动
  23. try {
  24. Class.forName("com.mysql.cj.jdbc.Driver");
  25. //2.定义sql
  26. String sql = "insert into account values(null,'王武',3000)";
  27. //3 获取Connection对象
  28. conn = DriverManager.getConnection("jdbc:mysql:///javaSQL", "root", "*******");
  29. //4 获取执行sql的对象 Statement
  30. stmt = conn.createStatement();
  31. //5 执行sql
  32. int count = stmt.executeUpdate(sql); //count结果为影响的行数
  33. //6 处理结果
  34. System.out.println(count);
  35. if(count >0){
  36. System.out.println("添加成功");
  37. }else{
  38. System.out.println("添加失败");
  39. }
  40. } catch (ClassNotFoundException e) {
  41. e.printStackTrace();
  42. } catch (SQLException throwables) {
  43. throwables.printStackTrace();
  44. }finally {
  45. //7 释放资源
  46. //避免 url、账号、密码错误造成的空指针异常
  47. if(stmt !=null){
  48. try {
  49. stmt.close();
  50. } catch (SQLException throwables) {
  51. throwables.printStackTrace();
  52. }
  53. }
  54. if(conn !=null){
  55. try {
  56. conn.close();
  57. } catch (SQLException throwables) {
  58. throwables.printStackTrace();
  59. }
  60. }
  61. }
  62. }
  63. }

select语句

练习:
定义一个方法,查询表的数据将其封装为对象,然后装载集合,返回
1.定义Data类
2.定义方法 public List findAll( ){ }
3.实现方法 select * from account;

public class Data {
    private int id;
    private String name;
    private double balance;
  //这里参略GetSet以及toString方法...
}
public class JDBCDemo01 {

    public static void main(String[] args) {
        List<Data> list= new JDBCDemo01().findAll();
        System.out.println(list);
        System.out.println(list.size());
    }
    //查询所有Data对象的方法
    public List<Data> findAll(){
        Connection conn=null;
        Statement stmt=null;
        ResultSet rs=null;
        List<Data> list=null;
        //1.注册驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql:///javaSQL", "root", "luoyu-3-233");
            //3.定义sql
            String sql="select * from account";
            //4.获取执行sql的对象
            stmt= conn.createStatement();
            //5.执行sql->获取结果集
            rs = stmt.executeQuery(sql);
            //6.遍历结果集,封装对象,装载集合

            Data data=null;
            list=new ArrayList<Data>();
            while (rs.next()) {
                //获取数据
                int id = rs.getInt("id");
                String name = rs.getString("name");
                double balance = rs.getDouble("balance");
                //创建data对象
                data=new Data();
                data.setId(id);
                data.setName(name);
                data.setBalance(balance);

                //装载集合
                list.add(data);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return list;
    }
}

JDBCUtils

抽取JDBC工具类:JDBCUtils
目的:简化书写
分析:
1.抽取注册驱动
2.抽取一个方法获取连接对象
需求:不用传递参数,保证工具类的通用性
方案:配置文件
jdbc.properties
url=
user=
password=
3.抽取一个方法注册资源
创建一个配置文件,将连接数据库所需的东西存入其中

url=jdbc:mysql:///javaSQL
user=root
password=******
driver=com.mysql.cj.jdbc.Driver

写一个JDBCUtils文件简化书写

/**
 *
 * 为了简化代码的书写,将注册驱动、连接对象以及关闭资源写入工具类中方便平时书写的简便性和效率
 */
public class JDBCUtils {
    //为了方便静态代码块调用,声明静态变量
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    //文件的读取,只需要读取一次即可拿到这些值->使用静态代码块
    static{
        //读取资源文件,获取值
        try {
            //1.创建Properties集合类
            Properties pro=new Properties();

            //获取src路径下文件的方式 --> ClassLoader 类加载器
//            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
//            URL res = classLoader.getResource("src/jdbc.properties");
//            String path = res.getPath();
//            System.out.println(path);
//这里在使用ClassLoader的时候遇到报错NoClassDefFoundError错误,导致Demo2无法调用JDBCUtils,暂未解决
            //2.加载文件
            pro.load(new FileReader("/Users/roderickkk/学习/Java代码/Java-project/JDBCcode/src/jdbc.properties"));
            //pro.load(new FileReader(path));
            //3.获取数据,复制
            url=pro.getProperty("url");
            user=pro.getProperty("user");
            password=pro.getProperty("password");
            driver=pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接的方法
     * @return 连接对象
     */
    public static Connection getConnection() throws SQLException {

        return DriverManager.getConnection(url,user,password);
    }

    /**
     * 释放资源
     * @param stmt
     * @param conn
     */
    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();
            }
        }
    }

    /**
     * 释放资源
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void close(ResultSet rs, 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();
            }
        }
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

最后在例子-select语句中使用JDBCUtils类简化操作成功

注册登陆

需求:
1.通过键盘录入用户名和密码
2.判断用户是否登陆成功
select * from user where username =”” and passowrd =””;
如果这个sql有查询结果则成功,反之失败
步骤:
1.创建数据库表 user
2.创建一个类

/**
 * 登陆注册练习
 */
public class JDBCDemo03 {

    public static void main(String[] args) {
        //1.键盘录入,接收用户名密码
        Scanner sc=new Scanner(System.in);
        System.out.println("用户名:");
        String username = sc.nextLine();
        System.out.println("密码:");
        String password = sc.nextLine();
        //2 调用方法
        boolean flag = new JDBCDemo03().login(username, password);
        //3 判断结果输出不同语句
        if(flag){
            //登陆成功
            System.out.println("登陆成功");
        }else {
            System.out.println("用户名或密码错误");
        }
    }
    /**
     * 登陆方法
     */
    public boolean login(String username,String password){
        if(username==null && password==null){
            return false;
        }
        Connection conn=null;
        Statement stmt=null;
        ResultSet rs=null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //2.定义sql
            String sql="select * from user where username = '"+username+"' and password = '" +password+"' ";
            //3.获取执行sql的对象
            stmt = conn.createStatement();
            //4.执行查询
            rs = stmt.executeQuery(sql);
            //5.判断
            return rs.next();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtils.close(rs,stmt,conn);
        }

        return false;
    }
}

JDBC控制事务

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

  • 开启事务
  • 提交事务
  • 回滚事务

使用Connection对象管理事务

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

    • 注意:在Catch中进行回滚 -> 一旦出现异常则回滚事务 ```java /**

      • 事务操作 / public class JDBCDemo04 {

      public static void main(String[] args) {

      Connection conn= null; PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null; try {

         //1.获取连接
         conn = JDBCUtils.getConnection();
         //开启事务
         conn.setAutoCommit(false);
      
        //2 定义sql
        String sql1="update account set balance = balance - ? where id = ?";
        String sql2="update account set balance = balance + ? where id = ?";
        //3 获取执行sql对象
        pstmt1 = conn.prepareStatement(sql1);
        pstmt2 = conn.prepareStatement(sql2);
        //4 设置参数
        pstmt1.setDouble(1,500);
        pstmt1.setInt(2,1);

        pstmt2.setDouble(1,500);
        pstmt2.setInt(2,2);
        //5 执行sql
        pstmt1.executeUpdate();

        //手动制造异常
        int i =3/0;
        pstmt2.executeUpdate();

        //提交事务
        conn.commit();
    } catch (Exception throwables) {
        try {
            //回滚事务
            if(conn!=null){
                conn.rollback();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        throwables.printStackTrace();
    }finally {
        JDBCUtils.close(pstmt1,conn);
        JDBCUtils.close(pstmt2,null);
    }
}

} ```