[数据库 04] JDBC java实现数据库连接

JDBC


1. JDBC

1. 驱动

构架:加一层

java.sql, javax.sql, 和数据库驱动包: mysql-connector-java.jar

2. JDBC程序

  1. 创建测试数据库
CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;

USE jdbcStudy;

CREATE TABLE `users`(
	id INT PRIMARY KEY,
	NAME VARCHAR(40),
	PASSWORD VARCHAR(40),
	email VARCHAR(60),
	birthday DATE
);
TRUNCATE TABLE `users`;
INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)
VALUES(1,'zhansan','123456','zs@sina.com','1980-12-04'),
(2,'lisi','123456','lisi@sina.com','1981-12-04'),
(3,'wangwu','123456','wangwu@sina.com','1979-12-04')
  1. 新建默认项目,项目下新建lib目录,导入maven repository 下载的mysql-connector-java.jar文件,

右键设置lib目录Add as Library,才能正常使用

  1. 万物皆对象
  • 加载驱动
  • 用户信息和url
  • 连接成功返回数据库对象
  • 执行sql对象
  • 操作
  • 释放连接
// 1. 加载驱动 固定写法,从jar包中加载驱动的Class对象
Class.forName("com.mysql.jdbc.Driver");
// 2. 用户信息和url
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";
		//如果mysql版本高于jdbc驱动jar包版本,SSL改为false, 否则报错
		// 时区问题: 加 &serverTimezone=GMT%2B8
String userName = "root";
String psw = "123456";
// 3. 连接,返回一个数据库对象(connection代表一个数据库)
Connection connection = DriverManager.getConnection(url, userName, psw);
// 4. 创建执行sql的对象
Statement statement = connection.createStatement();
// 5. 用执行sql的对象执行sql语句,并操作(查询query, 删除和插入都是update, )
String sql = "SELECT * from users";
ResultSet resultSet = statement.executeQuery(sql);
		// 返回一个链表,resultSet封装了所有查询出来的记录
while(resultSet.next()){
    System.out.println("id: "+ resultSet.getObject("id"));
    System.out.println("name: "+ resultSet.getObject("name"));
} 
// 6. 释放连接
resultSet.close();
statement.close();
connection.close();

3. JDBC中的对象

DriverManager:数据库驱动 Class.forName()获取

Connection: 连接数据库返回的对象 DtriverManager.getConnection()获取

Statement:执行sql语句的对象: connection.createStatement()获取

ResultSet: 返回记录的链表对象: statement.executeQ/U()获取

4. statement 对象(不推荐)

用于完成向数据库发送SQL语句的类

方法:

  1. statement.executeQuery(sql) 用于发送查询语句,返回ResultSet对象

  2. statement.executeUpdate(sql) 用于发送增,删,改 语句,返回一个整数(导致数据库的多少行发生了变化)

    //判断是否插入成功:
    String sql = "insert into user('id') values ()";
    int num = statement.executeUpdate(sql);
    if (num > 0){
        sout("插入数据成成功");
    }
    

实现对连接数据库和关闭数据库的工具类提取:

  1. src下添加配置文件 db.properties:
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false
username = root
psw = 123456
  1. 工具类:
public class JDBCUtils {
    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String psw = null;
	// 工具类写到static代码块中,需要用类加载器获取配置文件
    static {
        try{
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
            //在static中要使用getResourceAsStream()方法,必须使用类加载器来调用,否则无法使用(反射中)
            Properties properties = new Properties();
            properties.load(is);

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            psw = properties.getProperty("psw");

            Class.forName(driver);
        }catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username,psw);
    }
    //释放连接
    public static void releaseConnection(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
        if(resultSet != null){
            resultSet.close();
        }
        if(statement!= null){
            statement.close();
        }
        if(connection!= null){
            connection.close();
        }
    }
}

2. SQL注入(本质拼接)

select * from user where id = '' or '1=1'          -- sql注入攻击
select * from user where id = '' or '1=1' #        -- '#' 直接屏蔽后面的语句

因此, Statement对象不安全

3. PreparedStatement对象

防止SQL注入,并且效率更高

PS extends Statement, 通过继承修改父类的不足

preparedStatement对象的创建和Statement对象的创建函数不同

String sql = "insert into users(id, name, password, email, birthday values (?, ?, ?, ?, ?)" ;
// 使用预编译的sql语句,语句中?为占位符,用于传入参数查询。
PreparedStatement ps = connection.prepareStatement(sql);
ps.setObject(1, "value");//也可以直接设置setInt(), 防止注入
ps.setObject(2, "value");
ps.setObject(3, "value");
ps.executeUpdate();

流程: 1. 编写SQL2. 预编译3. 传递参数4. 执行

PreparedStatement 防止SQL注入的实现:

防止SQL注入的本质:是把传递进来的参数当作字符,如果其中存在'等转义字符,会被直接转义


IDEA连接数据库,切换表:

点击,在弹出的窗口中选择Schema切换表

4. JDBC操作事务

java操作事务

try{
    connection = ....getConnection();
    //java 只需要执行setAutoCommit关闭,就自动打开了事务,不需要写start transaction
    connection.setAutoCommit(false);
    sql。。。
    connection.commit();
}catch(SQLException e){
    connection.rollback();
}finally{
    connection.close();
}

5. 数据库连接池


原因: 数据库连接到释放过程十分浪费资源

池化技术: 准备一些预先的资源,过来就连接预先准备好的

eg: 本来: 开门--关门, 有池化技术: 派几个业务员等待开门(相当于池子)


3个重要参数:

最小连接数最大连接数 = 常用连接数: 业务最高承载量

如果业务数量超过最大连接数,需要排队等待

等待超时时间: 排队等待的最长时间


编写连接池,实现DataSource接口:

使用连接池后,开发不再需要编写连接数据库的代码

开源数据源实现:

DBCP, C3P0, Druid 可以去maven-repository找到相应的jar包

完全相同,实现连接的工具类需要修改,其他不修改。(jar包实现连接池)

posted @ 2021-12-01 17:15  Roy2048  阅读(89)  评论(0)    收藏  举报