java基础-JDBC

文章目录

  • 一、JDBC简介
  • 二、使用JDBC连接数据库的基本步骤
  • 三、JDBC 工具类构建
    • 1、资源释放工作的整合
    • 2、驱动防二次注册
    • 3.获取数据库Connection整合
    • 4、使用properties配置文件
  • 四、数据库的CRUDsql
    • insert
    • delete
    • query
    • update
  • 五、使用单元测试,测试代码
  • 六、Dao模式
    • 1. 新建一个dao的接口, 里面声明数据库访问规则
    • 2. 新建一个dao的实现类,具体实现接口定义的规则
    • 3. 直接使用实现
  • 七、Statement安全问题
  • 八、PrepareStatement

一、JDBC简介

JAVA Database Connectivity java 数据库连接

  • 为什么会出现JDBC

SUN公司提供的一种数据库访问规则、规范, 由于数据库种类较多,并且java语言使用比较广泛,sun公司就提供了一种规范,让其他的数据库提供商去实现底层的访问规则。 我们的java程序只要使用sun公司提供的jdbc驱动即可。

导入属于java提供的和数据库无关的类

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

导入具体数据库相关的jar包

//mysql
mysql-connector-java-5.1.7-bin.jar
//oracle
ojdbc5.jar

二、使用JDBC连接数据库的基本步骤

public static void main(String args[]) {
    try {
        //1.注册驱动
        DriverManager.registerDriver(new OracleDriver());
        //2.创建连接
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@103.10.87.51:1521/myoracle", "wangcf", "wangcf");
        //3.创建statement对象
        Statement statement = connection.createStatement();
        //4.获取结果
        ResultSet resultSet = statement.executeQuery("select * from test");
        while (resultSet.next()) {
            System.out.println("工号:" + resultSet.getInt(1) + 
            				   "姓名:" + resultSet.getString(2));

        }
    } catch(SQLException e) {
        e.printStackTrace();
    }finally{
        //5.释放资源
		resultSet.close();
        statement.close();
        connection.close();
        //JDBCUtil.release(connection, statement, resultSet);
	}
}

三、JDBC 工具类构建

创建一个工具类JDBCUtil对一些共用代码进行整合
对数据库的连接可以只维护这个类文件

1、资源释放工作的整合

在资源释放时也可能发生异常,资源释放的代码需要更加严谨。
并且将释放资源的代码进行整合,方便维护。

public class JDBCUtil {
    /**
     * 释放资源
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void release(Connection connection, Statement statement, ResultSet resultSet) {
        closeResultSet(resultSet);
        closeStatement(statement);
        closeConnection(connection);
    }

    /**
     * 释放结果集资源
     * @param resultSet
     */
    private static void closeResultSet(ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            resultSet = null;
        }
    }

    /**
     * 释放statement资源
     * @param statement
     */
    private static void closeStatement(Statement statement) {
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            statement = null;
        }
    }

    /**
     * 释放数据库连接资源
     * @param connection
     */
    private static void closeConnection(Connection connection) {
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            connection = null;
        }
    }
}

2、驱动防二次注册

//mysql手动注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//oracle手动注册驱动
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

但是在com.mysql.jdbc.Driver/oracle.jdbc.driver.OracleDriver这个类里面有静态代码块

//com.mysql.jdbc.Driver
java.sql.DriverManager.registerDriver(new Driver());
//oracle.jdbc.driver.OracleDriver
defaultDriver = new oracle.jdbc.OracleDriver();
DriverManager.registerDriver(defaultDriver);

该静态代码块在类加载时执行,所以等同于我们注册了两次驱动。
其实没这个必要的,最后形成以下代码,通过类加载来注册驱动

//mysql
Class.forName("com.mysql.jdbc.Driver");	
//oracle
Class.forName("oracle.jdbc.driver.OracleDriver");

注意

册驱动可以省略
在jar包 的ojdbc5.jar!\META-INF\services\java.sql.Driver该文件中有
oracle.jdbc.OracleDriver
此处提供了类名

3.获取数据库Connection整合

将注册驱动和获取数据库连接整合到工具类中

    /**
     * 获取数据库连接
     * @return
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            //通过类加载注册驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");
            //获取数据库连接
            connection = DriverManager.getConnection("jdbc:oracle:thin:@103.10.87.51:1521/myoracle", "wangcf", "wangcf");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

4、使用properties配置文件

java提供的JDBC和数据库提供的相关类之间的关联其实就是
驱动类、URL地址,数据库账号,数据库密码这4个字符串
通过创建properties文件使其解耦
这样在更换数据库时只需要修改properties类即可

  1. 在src文件下声明一个文件 jdbc.properties
driverClass=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@103.10.87.51:1521/myoracle
name=wangcf
password=wangcf
  1. 在工具类里面,使用静态代码块,读取属性

配置文件只需要在程序启动时读取一次,所以放到静态代码块中
在类加载时就读取配置

    private static String driverClass = null;
    private static String url = null;
    private static String name = null;
    private static String password = null;

    static {
        try {
            //创建properties配置文件对象
            Properties properties = new Properties();
            //使用类加载器读取src目录下的文件
            InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //导入输入流
            properties.load(is);
            //读取属性
            driverClass = properties.getProperty("driverClass");
            url = properties.getProperty("url");
            name = properties.getProperty("name");
            password = properties.getProperty("password");
            //释放资源
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

四、数据库的CRUDsql

用到的方法

statement.executeUpdate返回受影响的行数
statement.executeQuery返回ResultSet结果集

insert

//返回受影响的行数,期望的sql是inset、update、delete;但是写select也会有返回值
int count = statement.executeUpdate("select * from test");
System.out.println(count);  //2
count = statement.executeUpdate("insert into test values (00023,'张三')");
System.out.println(count); //1

delete

int count = statement.executeUpdate("delete from test where user_name='张三'");

query

//1.获取连接对象
connection = JDBCUtil.getConnection();
//3.创建statement对象
statement = connection.createStatement();
//4.获取结果
resultSet = statement.executeQuery("select * from test");
//遍历结果集
while (resultSet.next()) {
  System.out.println("工号:" + resultSet.getInt(1) + ";姓名:" + resultSet.getString(2));
}

update

//即使被更新过,再执行还会有一行受影响
int count = statement.executeUpdate("update test set user_name='小丽' where user_id='00002'");
System.out.println(count); //1

五、使用单元测试,测试代码

  1. 定义一个类, TestXXX , 里面定义方法 testXXX.
  2. 添加junit的支持。
    eclipse:右键工程 — add Library — Junit — Junit4
    idea:邮件工程–Add Frameworks Support
  3. 在方法的上面加上注解 , 其实就是一个标记。
   	@Test
   	public void testQuery() {
   		...
   	}
  1. 光标选中方法名字,然后右键执行单元测试。 或者是打开outline视图, 然后选择方法右键执行。

六、Dao模式

Data Access Object 数据访问对象

将访问数据库的规则,具体实现和业务逻辑分离
java基础-JDBC_第1张图片

1. 新建一个dao的接口, 里面声明数据库访问规则

/**
 * 定义操作数据库的方法
 */
public interface UserDao {
    /**
     * 查找全部数据
     */
    void findAll();

    /**
     * 插入数据
     */
    void insert();
}

2. 新建一个dao的实现类,具体实现接口定义的规则

public class UserDaoImpl implements UserDao {
    @Override
    public void findAll() {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            //1.获取连接对象
            connection = JDBCUtil.getConnection();
            //3.创建statement对象
            statement = connection.createStatement();
            //4.获取结果
            resultSet = statement.executeQuery("select * from test");
            //遍历结果集
            while (resultSet.next()) {
                System.out.println("工号:" + resultSet.getString(1) +
                        ";姓名:" + resultSet.getString(2));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(connection, statement, resultSet);
        }
    }

    @Override
    public void insert() {
        
    }
}

3. 直接使用实现

    public void testFindAll() {
        UserDao userDao = new UserDaoImpl();
        userDao.findAll();
    }

七、Statement安全问题

Statement执行 ,其实是拼接sql语句的
先拼接sql语句,然后在一起执行。

如果再登录时用到以下SQL语句

String sql = "select * from test where username='" + username + "' and password='" + password + "'";

并且用以下方式传值

		UserDao dao = new UserDaoImpl();
        userDao.login("zhangsan","1' or '1'='1");

将拼接成为如下sql语句

select * from test where username='zhangsan' and password='1' or '1'='1'

问题
前面先拼接sql语句, 如果变量里面带有了 数据库的关键字,那么一并认为是关键字,不认为是普通的字符串。
这样就导致不正确的密码也可以登录

八、PrepareStatement

该对象就是替换前面的statement对象。

相比较以前的statement, 预先处理给定的sql语句,对其执行语法检查。
在sql语句里面使用?占位符来替代后续要传递进来的变量。
后面进来的变量值,将会被看成是字符串,不会产生任何的关键字。

//先定义sql语句
String sql = "select * from test where username=? and password=?";
ps = connection.prepareStatement(sql);
//占位符 从 1 开始
ps.setString(1, username);
ps.setString(2, password);
//ps.setInt();
//执行sql
resultSet = ps.executeQuery();

你可能感兴趣的:(java基础)