MySQL--06

一、PreparedStatement和Statement的区别

1、PreparedStatement使用?占位符代替参数

String sql  = "update users set name = ? where id = ?";

预编译sql,然后设置结果

 public static void main(String[] args) {
login("' or ' 1=1","123456");
}

public static void login(String username,String password){
Connection conn = null;
PreparedStatement stat = null;
ResultSet rs = null;
try {
conn = utils.getConn();

String sql = "select * from users where `name`=? and psw=?";
stat = conn.prepareStatement(sql);
stat.setString(1,username);
stat.setString(2,password);
rs = stat.executeQuery();
if (rs.next()) {
System.out.println("rs:" + rs.getObject("id")+" "+rs.getObject("name")+" "+rs.getObject("psw"));
}

} catch (SQLException e) {
e.printStackTrace();
}finally{
utils.relax(conn,stat,null);
}
}
}

//此时就不会再出现sql注入问题,PreparedStatement把传递进来的参数当作字符,假设传递的参数中有转译字符就直接忽略
//''会被直接转义

PreparedStatement.set(1,"licunzhi");//意思就是第一个?设置值为“liucnzhi”

PreparedStatement.set(2,"why");//第二个?设置值为why....以此类推

二、使用JDBC执行事务

package com.baidu.JDBC;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement stat = null;
        ResultSet rs = null;
        try {
            conn = utils.getConn();
            //关闭自动提交  这里直接开启一个事务 不需要像数据库一样操作
            conn.setAutoCommit(false);


            String sql1 = "update account set money=money-100 where id=1";
            stat = conn.prepareStatement(sql1);
            stat.executeUpdate();

            String sql2 = "update account set money=money+100 where id=2";
            stat = conn.prepareStatement(sql2);
            stat.executeUpdate();

            //业务完毕 提交事务
            conn.commit();
            System.out.println("转账成功");

        } catch (SQLException e) {
            try {
                //失败则回滚数据,不写也会自动回滚
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally{
            utils.relax(conn,stat,null);
        }
    }
}

代码实现:

1、开启事务

2、一组业务执行完毕,提交事务

3、可以再catch语句中i希纳是的定义回滚数据,但默认失败就会回滚

三、数据库连接池

常见的数据库连接池:

DBCP C3P0  【Druid(德鲁伊)  阿里巴巴】

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

连接池可以自己手写,实现接口DataSource

使用数据库连接池之后我们就不需要编写连接数据库的代码了

1、dbcp

首先将两个jar包导入程序中,add librarys

接下来配置文件百度一个

#连接设置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC
username=root
password=space999

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

接下来工具类,省去了读取配置文件每个字段的步骤

package space.bilibili.com;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class Jdbc_Utils {
    private static Connection conn = null;
    private static DataSource dataSource = null;
    static{
        try{
            //将配置文件放入流中
            InputStream in = Jdbc_Utils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            //加载读取配置文件的类
            Properties properties = new Properties();
            //加载流中的配置文件
            properties.load(in);

            dataSource = BasicDataSourceFactory.createDataSource(properties);
            conn = dataSource.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConn() throws SQLException {
        return dataSource.getConnection();
    }
    //释放资源
    public static void release(Connection conn,Statement stat,ResultSet rs){
        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();
            }
        }
    }
}

接下来就是测试插入代码:

package space.bilibili.com;

import space.urbeautiful.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class TestInsert {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement stat = null;
        ResultSet rs = null;
        try {
            conn = Jdbc_Utils.getConn();
            String sql = "insert into account(id,`name`,money) values(5,'why',20000)";
            stat = conn.prepareStatement(sql);
            int i = stat.executeUpdate();
            if(i>0){
                System.out.println("插入成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn,stat,rs);
        }
    }
}

2、C3P0

原文地址:https://www.cnblogs.com/jzspace/p/13055149.html