JAVA操作数据库以及连接池的使用

这篇博客详细介绍了Java使用JDBC进行数据库操作的基本步骤,包括加载驱动、建立连接、执行SQL以及释放资源。同时,文章探讨了数据库中文乱码的解决方案,强调了PreparedStatement在防止SQL注入方面的重要性,并比较了Statement与PreparedStatement的性能。此外,还讲解了批处理技术以及如何利用DBCP和Druid连接池提升数据库性能。最后,提到了连接池工具类的使用,确保资源的有效管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JDBC

java操作数据库的基本步骤

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

public class Demo1 {
    public static void createTable() throws SQLException, ClassNotFoundException {
        //1、加载数据库驱动
        Class.forName("com.mysql.jdbc.Driver");//将这个类加载到内存
        //2、通过驱动管理器,获取JDBC的连接对象
//        三个参数:
//              数据库连接地址:主协议:子协议://ip地址:端口号/数据库名称
//                    mysql: jdbc:mysql://localhost:3306/localhost
//                    oracle:jdbc:oracle:thin:@ip地址:1521:/ORCL
//              账号以及密码
         Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "********");
         //3、通过连接对象,创建SQL执行对象(SQL执行环境)
        Statement stat = conn.createStatement();
         //4、通过SQL执行对象  执行SQL语句
        stat.execute("create table person(id int,nickname varchar (32))");
        //5、释放连接
        stat.close();
        conn.close();
    }
    public static void insertDate() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection coon = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8", "root", "********");
        Statement state = coon.createStatement();
        state.executeUpdate("insert into person values (2,'张三')");
        state.close();
        coon.close();

    }
}

数据库中插入中文出现乱码的解决方法:
DriverManager.getConnection("jdbc:mysql://localhost:3306/test2/?useUnicode=true&characterEncoding=utf-8", “root”, “********”);

JDBC查询数据库

public static void selectPerson() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncodeing=utf-8", "root", "hjr8331251");
        Statement statement = conn.createStatement();
        //执行查询sql语句并且得到结果集
        ResultSet resultSet = statement.executeQuery("select * from person");
        //通过while循环将这个结果集中的数据取出
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String nickname = resultSet.getString("nickname");
            System.out.println("id="+id+"nickname="+nickname);
        }
        conn.close();
        statement.close();
        resultSet.close();//结果集也需要关闭
    }

SQL注入问题 *

进行用户登录时, 输入不存在的帐号 和 如下的密码:
1’ or ‘1’=‘1
结果显示登录成功.
因为用户输入的密码, 与我们的查询语句拼接后, 使得我们的查询语句产生了歧义:
原查询语句:
select * from xzk_user where username=’’ and password=‘密码’
拼接后:
select * from xzk_user where username=‘hahahaheiheihei’ and password=‘1’ or
‘1’=‘1’

解决sql注入问题 *

我们可以将SQL语句与参数分离,将参数作为SQL的特殊部分进行预处理.

PreparedStatement 预编译的SQL执行环境

  1. 将未拼接参数的SQL语句, 作为SQL指令, 先传递给数据库 进行编译.
  2. 再将参数传递给数据库, 此时传递的参数不会再作为指令执行, 只会被当作文本存在. 操作流程与Statement基本一致:
  3. 如何得到一个PreparedStatement 对象
    PreparedStatement state =conn.prepareStatement(“预编译的SQL语句”);
  4. 预编译的SQL语句如何编写 需要填充参数的位置, 使用?代替即可! 例如:
    select id from xzk_user where username=? and password=?
  5. 参数如何填充 state.setXXX(int index,XXX value); setXXX中XXX指的是数据类型, 参数1: index : SQL语句中?的索引值 , 从1开始 参数2: value : 填充的参数值.
  6. 如何执行填充完毕参数的SQL
  • boolean execute();
  • int executeUpdate();
  • ResultSet executeQuery();

PreparedStatement与Statement谁的性能高?

看是什么数据库
在mysql中, preparedStatement原理是拼接SQL, 所以Statement性能高.
在Oracle中, preparedStatement原理是对SQL指令进行预处理, 再传递的参数不具备特殊含义.有更好
的SQL缓存策略,PreparedStatement高.

批处理技术

将多条语句, 放到一起批量处理 .
批处理的原理: 将多条SQL语句, 转换为一个SQL指令. 显著的提高大量SQL语句执行时的数据库性能.
Statement对象使用流程:

  1. 得到Statement对象 Statement state = conn.createStatement();
  2. 将一条SQL语句, 加入到批处理中. state.addBatch(String sql);
  3. 执行批处理 state.executeBatch();
  4. 清空批处理 state.clearBatch(); PreparedStatement对象使用流程:
  5. 得到PreparedStatement对象 PreparedStatement state = conn.prepareStatement(“预编译的SQL”);
  6. 填充预编译的参数 state.setXXX(1,填充参数);
  7. 将一条填充完毕参数的SQL, 加入到批处理中. state.addBatch();
  8. 执行批处理 state.executeBatch();
  9. 清空批处理 state.clearBatch();

Properties 作为配置文件

Properties类 是Java中的Map集合的实现类.
.properties文件 用于通过文件描述一组键值对!
.properties文件 ,可以快速的转换为Properties类的对象.
文件中内容的格式:
文件内容都是字符串 , 键与值之间通过等号连接 , 多个键值对之间换行分割.
例如:
url=xxx
user=xxx
password=xxx
如何将文件 转换为 集合:
步骤:

  1. 创建Properties对象 Properties ppt = new Properties();
  2. 创建一个字节输入流 , 指向.properties文件 InputStream is = new FileInputStream(“文件地址”);
  3. 将字节输入流, 传递给properties对象, 进行加载. ppt.load(is);

连接池(DataSource)的使用 *

DBCP连接池的使用步骤 *

  1. 引入相关的jar文件
  • dbcp.jar
  • poll.jar
  1. 将配置文件引入
  2. 将配置文件, 转换为Properties对象 Properties ppt = new Properties(); ppt.load(配置文件的输入流);
  3. 通过连接池的工厂类(BasicDataSourceFactory)的创建连接池的方法(createDataSource()) DataSource ds = BasicDataSourceFactory.createDataSource(ppt);
  4. 从连接池中 获取连接对象 Connection conn = ds.getConnection();

德鲁伊连接池的使用步骤 *

  1. 引入相关的jar文件
  • druid-1.0.9.jar
  1. 将配置文件引入
  2. 将配置文件, 转换为Properties对象 Properties ppt = new Properties(); ppt.load(配置文件的输入流);
  3. 通过连接池的工厂类(DruidDataSourceFactory)的创建连接池的方法(createDataSource()) DataSource ds = DruidDataSourceFactory.createDataSource(ppt);
  4. 从连接池中 获取连接对象 Connection conn = ds.getConnection();

连接池工具类

Druid

public class DruidUtil{
    private static DataSource data = null;
    static {
    InputStream is = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
        Properties ppt = new Properties();
        try {
            ppt.load(is);
            data = DruidDataSourceFactory.createDataSource(ppt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 用于从DBCP连接池中 获取一个连接
     * @return DBCP连接池中的一个连接对象.
     */
    public static Connection getConnection() {
        try {
            return data.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 用于释放连接 , 执行环境 , 结果集 等资源
     * @param conn 要释放的连接资源
     * @param state 要释放的执行环境资源
     * @param result 要释放的结果集资源
     */
    public static void close(Connection conn,Statement state,ResultSet result) {
        if(result != null) {
            try {
                result.close();
            } catch (SQLException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(state != null) {
            try {
                state.close();
            } catch (SQLException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

DBCP

public class DBCPUtil {
    private static DataSource data = null;

    static {
        InputStream is = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcp.properties");
        Properties ppt = new Properties();
        try {
            ppt.load(is);
            data = BasicDataSourceFactory.createDataSource(ppt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 用于从DBCP连接池中 获取一个连接
     *
     * @return DBCP连接池中的一个连接对象.
     */
    public static Connection getConnection() {
        try {
            return data.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 用于释放连接 , 执行环境 , 结果集 等资源
     *
     * @param conn   要释放的连接资源
     * @param state  要释放的执行环境资源
     * @param result 要释放的结果集资源
     */
    public static void close(Connection conn, Statement state, ResultSet result) {
        if (result != null) {
            try {
                result.close();
            } catch (SQLException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if (state != null) {
            try {
                state.close();
            } catch (SQLException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值