MySQL数据库之JDBC入门

目录

JDBC入门

JDBC各个类详解 

DriverManager:驱动管理对象

Connection:数据库连接对象

Statement:执行sql的对象

PreparedStatement:执行sql的对象

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

抽取JDBC工具类

JDBC 登录案例

JDBC控制事务


 

JDBC入门

  1. 概念:Java DataBase Connectivity     Java数据库连接

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

      2. 快速入门:基本操作步骤在代码部分。这只是一段了解JDBC的代码,并不完善,完善代码请看后面。

package JDBC;

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

/**
 * 导包:导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
 * 1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
 * 2.右键-->Add As Library
 * <p>
 * 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
 * 2. 注册驱动
 * 3. 获取数据库连接对象 Connection
 * 4. 定义sql
 * 5. 获取执行sql语句的对象 Statement
 * 6. 执行sql,接受返回结果
 * 7. 处理结果
 * 8. 释放资源
 */
public class jdbcConnect {
    public static void main(String[] args) throws Exception {
        //  1. 加载驱动
        Class.forName( "com.mysql.jdbc.Driver" );
        //  2. 获取数据连接对象
        Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/school", "root", "root" );
        //  3. 定义sql
        String sql = "UPDATE student SET id =101 WHERE id=102";
        //  4. 获取执行sql语句的对象 Statement
        Statement stat = conn.createStatement();
        //  5. 执行sql
        //  返回值是受影响的行数
        int i = stat.executeUpdate( sql );
        //  6. 处理结果
        System.out.println( i );
        //  6. 释放资源
        stat.close();
        conn.close();
    }
}

====================================================
1

Process finished with exit code 0

JDBC各个类详解 

DriverManager:驱动管理对象

      功能:
        (1)注册驱动:告诉程序该使用哪一个数据库驱动jar
                  static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。 
                  写代码使用:  Class.forName("com.mysql.jdbc.Driver");
                  通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
                  static {
                        try {
                            java.sql.DriverManager.registerDriver(new Driver());
                        } catch (SQLException E) {
                            throw new RuntimeException("Can't register driver!");
                        }
                    }

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

        (2) 获取数据库连接:
                   * 方法:static Connection getConnection(String url, String user, String password) 
                   * 参数:
                         * url:指定连接的路径
                               * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
                               * 例子:jdbc:mysql://localhost:3306/db3
                               * 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
                    * user:用户名
                    * password:密码 

Connection:数据库连接对象

    功能:
            1. 获取执行sql 的对象
                * Statement createStatement()
                * PreparedStatement prepareStatement(String sql)  
            2. 管理事务:
                * 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
                * 提交事务:commit() 
                * 回滚事务:rollback() 

Statement:执行sql的对象

    功能:
            1. boolean execute(String sql) :可以执行任意的sql 了解 
            2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
                * 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
            3. ResultSet executeQuery(String sql)  :执行DQL(select)语句 ,返回一个结果集

案例:向employee表添加一条数据。

package JDBC;

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

/**
 * student表 添加一条语句 insert
 */
public class JDBCDemo1 {
    public static void main(String[] args) {
        Statement stat = null;
        Connection conn = null;

        try {
            //  1.加载驱动
            Class.forName( "com.mysql.jdbc.Driver" );
            //  2.定义sql
            String sql = "insert into employee values(7,'赵虎',19,2)";
            //  3.获取Connection对象
            conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/school", "root", "root" );
            //  4.获取sql对象
            stat = conn.createStatement();
            //  5.执行sql
            int count = stat.executeUpdate( sql );
            //  6.操作结果
            if (count > 0) {
                System.out.println( "插入数据成功" );
            } else {
                System.out.println( "插入数据失败" );
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //  7.释放资源
            //  防止空指针异常
            if (stat != null) {
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (conn != null) {
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

=================================================
插入数据成功

Process finished with exit code 0

PreparedStatement:执行sql的对象

  (1) SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
                1. 输入用户随便,输入密码:a' or 'a' = 'a
                2. sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 

  (2)解决sql注入问题:使用PreparedStatement对象来解决
            预编译的SQL:参数使用?作为占位符
            步骤:
                1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
                2. 注册驱动
                3. 获取数据库连接对象 Connection
                4. 定义sql
                    * 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
                5. 获取执行sql语句的对象 PreparedStatement  Connection.prepareStatement(String sql) 
                6. 给?赋值:
                    * 方法: setXxx(参数1,参数2)
                        * 参数1:?的位置编号 从1 开始
                        * 参数2:?的值
                7. 执行sql,接受返回结果,不需要传递sql语句
                8. 处理结果
                9. 释放资源

   (3) 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
                1. 可以防止SQL注入
                2. 效率更高

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

      功能: 

              * boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
             * getXxx(参数):获取数据
                        * Xxx:代表数据类型   如: int getInt() ,    String getString()
                        * 参数:
                                 1. int:代表列的编号,从1开始   如: getString(1)
                                 2. String:代表列名称。 如: getDouble("id")   表示获取employee表里id列的值

             * 使用步骤:
                                 1. 游标向下移动一行
                                 2. 判断是否有数据
                                3. 获取数据
案例:定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。(省略了定义employee实体类的过程)

package JDBC;

import domain.employee;

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

/**
 * * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。
 * 1. 定义Emp类
 * 2. 定义方法 public List<Emp> findAll(){}
 * 3. 实现方法 select * from emp;
 */
public class JDBCDemo4 {

    public static void main(String[] args) {
        //调用findAll方法
        List<employee> list = new JDBCDemo4().findAll();
        for (employee employee : list) {
            System.out.println( employee );
        }
    }

    public List<employee> findAll() {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        List<employee> list = null;

        try {
            //  1.加载驱动
            Class.forName( "com.mysql.jdbc.Driver" );
            //  2.定义sql
            String sql = "select * from employee";
            //  3.获取Connection对象
            conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/school", "root", "root" );
            //  4.获取执行sql的对象
            stat = conn.createStatement();
            //  5.执行sql
            rs = stat.executeQuery( sql );

            //  6.处理结果,遍历结果集,封装对象,装载到集合中
            list = new ArrayList<employee>();
            employee emp = null;
            while (rs.next()) {
                //创建employee对象
                emp = new employee();
                emp.setId( rs.getInt( "id" ) );
                emp.setName( rs.getString( "name" ) );
                emp.setAge( rs.getInt( "age" ) );
                emp.setDep_id( rs.getInt( "dep_id" ) );
                //添加到集合中
                list.add( emp );
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //  释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (stat != null) {
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return list;
    }
}
============================================================
employee{id=1, name='张三', age=20, dep_id=3}
employee{id=2, name='李四', age=21, dep_id=3}
employee{id=3, name='王五', age=20, dep_id=3}
employee{id=4, name='老王', age=20, dep_id=2}
employee{id=5, name='大王', age=22, dep_id=2}
employee{id=6, name='小王', age=18, dep_id=2}

Process finished with exit code 0

抽取JDBC工具类

目的:简化书写

分析
         1. 注册驱动抽取
         2. 抽取一个方法获取连接对象
           **   不传递参数,必须保证工具类的通用性能,需要创建一个配置文件,配置文件里存放数据库地址,用户名,密码,驱动
         3. 抽取一个方法释放资源

 配置文件

url=jdbc:mysql://localhost:3306/school
user=root
password=root
driver=com.mysql.jdbc.Driver

JDBC工具类: 

package tool;

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

/**
 * JDBC工具类
 */
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( "jdbc.properties" );
            String path = res.getPath();

            //  2.加载文件
//            pro.load( new FileReader( "E:\\IdeaProject\\ShuangYuan\\day15\\jdbc.properties" ) );
            pro.load( new FileReader( path ) );

            //  3.获取数据,赋值
            url = pro.getProperty( "url" );
            user = pro.getProperty( "user" );
            password = pro.getProperty( "password" );
            driver=pro.getProperty( "driver" );
            Class.forName( driver );
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     *
     * @return Connection连接对象
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection( url,user,password );
    }


    /**
     * 释放资源
     *
     * @param stat
     * @param conn
     */
    public static void close(ResultSet rs, Statement stat, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (stat != null) {
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

JDBC 登录案例

需求
          1.  通过键盘录入用户名和密码
          2.  判断用户登录是否成功,反馈信息打印到控制台

创建User表

CREATE TABLE USER(
	id  INT PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(32),
	PASSWORD VARCHAR(32)
);

INSERT INTO USER VALUES(NULL,'zhangsan','123');
INSERT INTO USER VALUES(NULL,'lisi','456');

 登录代码

package JDBC;

import tool.JDBCUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

/**
 * 需求:
 * 1. 通过键盘录入用户名和密码
 * 2. 判断用户是否登录成功
 */
public class JDBCDemo5 {

    public static void main(String[] args) {
        Scanner sc=new Scanner( System.in );
        System.out.println("请输入用户名:");
        String username = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();

        boolean login = new JDBCDemo5().login( username, password );
        if(login){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }
    }

    /**
     * 登录方法
     * @param username
     * @param password
     * @return
     */
    public boolean login(String username, String password) {
        //  若用户名和密码为空,返回false
        if (username == null || password == null) {
            return false;
        }

        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            //  1.获取连接
            conn = JDBCUtils.getConnection();
            //  2.定义sql
            String sql = "select * from user where username = '" + username + "' and password = '" + password + "' ";
            //  3.获取执行sql的对象
            stat = conn.createStatement();
            //  4.执行SQL语句
            rs = stat.executeQuery( sql );

            return rs.next();

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //  5.释放资源
            JDBCUtils.close( rs, stat, conn );
        }


        return false;
    }
}

测试结果: 

请输入用户名:
zhangsan
请输入密码:
123
登录成功

Process finished with exit code 0
==========================================
请输入用户名:
zhangsan
请输入密码:
32424324
登录失败

Process finished with exit code 0
==========================================
请输入用户名:
lisi
请输入密码:
456
登录成功

Process finished with exit code 0

注意:上述代码是有问题的,如下用户名和密码在数据库中都不存在,但是却登录成功了,这是为什么呢?其实我们看下它的sql语句就可以看出来,最后的字符串拼接,or 'a' = 'a' ,or后面是一个恒等式,所以自然就成立,这就是SQL注入问题--(SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令)。
sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 

请输入用户名:
dasd sa
请输入密码:
a' or 'a' = 'a
登录成功

Process finished with exit code 0

解决sql注入问题的方案:使用PreparedStatement对象来解决

预编译的SQL:参数使用 ? 作为占位符

            //  1.获取连接
            conn = JDBCUtils.getConnection();
            //  2.定义sql
            String sql = "SELECT * from user WHERE username=? and password=?";
            //  3.获取执行sql的对象
            ps = conn.prepareStatement( sql );
            //  4.给?赋值
            ps.setString(1,username);
            ps.setString( 2,password );
            //  5.执行查询,不需要传递sql
            rs = ps.executeQuery();

JDBC控制事务

(1)事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
(2 )  操作:
              1. 开启事务
              2. 提交事务
              3. 回滚事务
(3)使用Connection对象来管理事务
              * 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
                      * 在执行sql之前开启事务
              * 提交事务:commit() 
                      * 当所有sql都执行完提交事务
              * 回滚事务:rollback() 
                     * 在catch中回滚事务 

public class JDBCDemo10 {

	    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
	            //2.1 张三 - 500
	            String sql1 = "update account set balance = balance - ? where id = ?";
	            //2.2 李四 + 500
	            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 e) {
	            //事务回滚
	            try {
	                if(conn != null) {
	                    conn.rollback();
	                }
	            } catch (SQLException e1) {
	                e1.printStackTrace();
	            }
	            e.printStackTrace();
	        }finally {
	            JDBCUtils.close(pstmt1,conn);
	            JDBCUtils.close(pstmt2,null);
	        }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值