数据库驱动和jdbc

由于不同的数据库有不同的驱动,于是就有SUN公司为了简化开发人员,就对数据库统一提供了java操作数据库一个规范(JDBC)。这些规范的实现由具体的厂商去做!对于开发人员来说只需要掌握jdbc的接口操作即可。我们只需要导入对应的数据库的驱动包即可。

// 创建连接的工具类
package com.dbh.student02.utils;

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


public class JdbcUtils {
        private static  String  driver=null;
        private static String  url=null;
        private static String  username=null;
         private static String  pwd=null;
    properties
    static{
        try{
            
            // 使用db.properties
            //JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties")是返回一个读取指定资源的输入流
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            //创建一个空的properties
            Properties properties=new Properties();
           //pro.load(in)是从输入流中读取属性列表
            properties.load(in);
				
            // 从properties读取内容并给他赋值
            driver=  properties.getProperty("driver");
            url=  properties.getProperty("url");
            username=properties.getProperty("username");
            pwd=properties.getProperty("password");

            // 加载驱动,只需要加载一次
            Class.forName(driver);

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // 获得连接
    // connection 代表数据库 connection可以开启事务,可以回滚事务可以设置是否自动提交
       public static Connection getConnection() throws SQLException {
        return  DriverManager.getConnection(url, username, pwd);
       } 
    
    // 关闭连接
	// Statement 执行sql的对象 PreparedStatement也是sql的对象但是相对于statement更加安全 
    
    // 查询statement.executeQuery 返回值ResultSet
    // 删除,修改,增加多用一个,只是具体的sql   statement.executeUpdate() 返回值是受影响的行数
    // statement.execute执行全部
    
    //ResultSet可以获得指定字段的值  resultSet.getInt(),resultSet.getString(), 	           resultSet.getObject(), resultSet.getFloat(),resultSet.getDate(), resultSet.getDouble()...
    
    
    
    public static void release(Connection conn, ResultSet rs, Statement st){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }



}
// 增加
package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class TestInster {


    public static void main(String[] args) {
        Connection conn=null;
        ResultSet rs=null;
        Statement st=null;
        try{
            conn= JdbcUtils.getConnection();
            st=conn.createStatement();
            String sql="insert into user(`username`,`pwd`,`sex`,`age`) VALUES('ybt','123','男',12)";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("插入成功");
            }else{
                System.out.println("插入失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,rs,st);
        }


    }
}


// 删除
package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class TestDelete {

    public static void main(String[] args) {
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;






        try {
            conn=JdbcUtils.getConnection();
            st=conn.createStatement();
            String sql="DELETE FROM  `user`  WHERE id=1";
            int i=st.executeUpdate(sql);
            if(i>0){
                System.out.println("删除成功");
            }else{
                System.out.println("删除失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,rs,st);
        }


    }


}

//修改
package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;


        try {
            conn= JdbcUtils.getConnection();
            st=conn.createStatement();
            String sql="UPDATE `user` SET pwd=789 WHERE id=2";
            int i=st.executeUpdate(sql);
            if(i>0){
                System.out.println("修改成功");
            }else{
                System.out.println("修改失败");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,rs,st);
        }


    }
}
// 查看
package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class TestSelect {

    public static void main(String[] args) {
        Connection conn=null;
        ResultSet rs=null;
        Statement st=null;


        try {
            conn= JdbcUtils.getConnection();
            st=conn.createStatement();
            String sql="select *from `user`";
            rs = st.executeQuery(sql);
            while (rs.next()) {
                System.out.println(rs.getString("username"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,rs,st);
        }


    }


}

SQL注入的问题

sql存在漏洞,会被攻击,导致数据泄露。

select *from user where username=’‘or ’ 1=1’ and pwd =123456,**sql存在拼接 **

PreparedStatement

可以防止SQL注入,效果更好

本质就是把传递过来的参数当作字符。

package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class SQLPreparedStatement {


    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;


        try {
            conn= JdbcUtils.getConnection();
            //可以使用?占位符代替参数
            String sql="insert into `user`(`username`,`pwd`,`sex`,`age`)  values(?,?,?,?)";
            ps= conn.prepareStatement(sql);//预编译SQL,先写SQL,然后不执行
            ps.setString(1,"dkz");
            ps.setString(2,"123");
            ps.setString(3,"男");
            ps.setInt(4,100);

            int i = ps.executeUpdate();

            if(i>0){
                System.out.println("插入成功");
            }else{
                System.out.println("插入失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }




}
IDEA连接mysql

在这里插入图片描述

JDBC操作事务

要么成功,要么失败

ACID原则

原子性:要么全部完成,要么全部不完成

一致性:总数不变

持久性:多个进程互不干扰

隔离性:一旦提交就不可逆,持久化到数据库了

隔离性的问题:

​ 脏读:一个事务读取了另一个没有提交的事务

​ 不可重复读: 在同意个事务内,重复读取表中的数据,表的数据发生了改变

​ 幻读/虚读:在一个事务内,读取到了,别人插入的数据。导致前后读出来的结果不一致

​ 事务的个隔离级别(mysql默认可重复读):

​ 读未提交,读以提交,可重复读,可串行

模拟转账

package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class TestTransaction {
    public static void  main(String[] args)  {
        Connection conn=null;
        ResultSet rs=null;
        PreparedStatement ps=null;


        try {
           conn= JdbcUtils.getConnection();
           //关闭数据库的自动提交,自动会开启事务
           conn.setAutoCommit(false);

           //执行转账业务
           String sql="update `account` set `money`=money-100 where name= 'A'";
            ps=conn.prepareStatement(sql);
            ps.executeUpdate();
              // 模仿失败,如果没加事务,理论上面的sql应该是成功的。但是并没有,这样更好的证明了事务之间是不可分割的,要么失败,要么成功.
            int i=1/0;

            

            String sql2="update `account` set `money`=money+100 where name= ''";
            ps=conn.prepareStatement(sql2);
            ps.executeUpdate();

            //业务执行完毕需要提交事务
            conn.commit();
            System.out.println("操作成功");
           //提交完成事务后需要重新启动
            conn.setAutoCommit(true);
        } catch (SQLException e) {
            try {
                System.out.println("操作失败,需要回滚");
                conn.rollback();//如果失败就回滚事务,就算没写,也会自动回滚,只要是在执行的事务额过程中报了错误。
            } catch (SQLException e1) {
                e1.printStackTrace();
            }

            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,rs,ps);
        }


    }

}
数据库连接池

数据库连接—》执行完毕—》释放

连接-- 释放 十分浪费系统资源

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

更据你常用的连接数,来设置最小的连接数

最小连接数:10

最大连接数: 100 业务的承载上限

如果是超过了最大链接数就需要排队等待

等待超时:100ms

编写连接池,只需要实现一个接口 DataSource

开源数据源实现

DBCP

C3P0

Druid: 阿里巴巴的

使用这些数据库连接池后,我们在项目开发中,就不需要编写连接数据库的代码

DBCP

需要用的jar包(以及数据库的驱动)

在这里插入图片描述

# 连接设置 这里的名字,是DBCP数据源定义好的
dirverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/dbhblog?userUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456

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

#最大连接数量
maxActive=50

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

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

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;//】
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=utf8

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

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=

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

package com.dbh.student02.demo;

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

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class TestDBCP {
    private static DataSource dataSource=null;

    static{
        try {
            InputStream in = TestDBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            Properties properties=new Properties();
            properties.load(in);

        //创建数据源工厂模式--》创建
            dataSource = BasicDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            e.printStackTrace();
        }


    }



    // 获取连接
    public static Connection getConnection() throws SQLException {
        return  dataSource.getConnection();//从数据源获取连接
    }


    // 关闭连接

    public static void release(Connection conn, ResultSet rs, Statement st){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}


//  使用帮助类得到具体类

package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class TestSelect {

    public static void main(String[] args) {
        Connection conn=null;
        ResultSet rs=null;
        Statement st=null;


        try {
            conn= TestDBCP.getConnection();
            st=conn.createStatement();
            String sql="select *from `user`";
            rs = st.executeQuery(sql);
            while (rs.next()) {
                System.out.println(rs.getString("username"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            TestDBCP.release(conn,rs,st);
        }


    }


}

C3P0

需要的jar包
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 默认配置,如果没有指定则使用这个配置 -->
    <default-config>
        <property name="user">root</property>
        <property name="password">123456</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/zhanghanlun?userUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>


        <property name="checkoutTimeout">30000</property>
        <property name="idleConnectionTestPeriod">30</property>
        <property name="initialPoolSize">3</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">2</property>
        <property name="maxStatements">200</property>
    </default-config>
    <!-- 命名的配置,可以通过方法调用实现 -->
    <named-config name="MYSQL">
        <property name="user">root</property>
        <property name="password">123456</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/dbhblog?userUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <!-- 如果池中数据连接不够时一次增长多少个 -->
        <property name="acquireIncrement">5</property>
        <!-- 初始化数据库连接池时连接的数量 -->
        <property name="initialPoolSize">20</property>
        <!-- 数据库连接池中的最大的数据库连接数 -->
        <property name="maxPoolSize">25</property>
        <!-- 数据库连接池中的最小的数据库连接数 -->
        <property name="minPoolSize">5</property>
    </named-config>
</c3p0-config>


package com.dbh.student02.demo;



import com.mchange.v2.c3p0.ComboPooledDataSource;


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


public class TestC3P0 {
    private static ComboPooledDataSource dataSource=null;


    static {
        try{
            // 代码配置
/*            dataSource=new ComboPooledDataSource("MYSQL");
            dataSource.setDriverClass();
            dataSource.setUser();
            dataSource.setPassword();
            dataSource.setJdbcUrl();
            dataSource.setMaxPoolSize();*/
        dataSource=new ComboPooledDataSource("MYSQL");//配置文件写法,一般是使用这一种
        }catch (Exception e){
           e.printStackTrace();
        }
    }



    // 获取连接
    public static Connection getConnection() throws SQLException {
        return  dataSource.getConnection();//从数据源获取连接
    }


    // 关闭连接

    public static void release(Connection conn, ResultSet rs, Statement st){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }






}



// 实现
package com.dbh.student02.demo;

import com.dbh.student02.utils.JdbcUtils;

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

public class TestSelect {

    public static void main(String[] args) {
        Connection conn=null;
        ResultSet rs=null;
        Statement st=null;


        try {
            conn= TestC3P0.getConnection();
            st=conn.createStatement();
            String sql="select *from `user`";
            rs = st.executeQuery(sql);
            while (rs.next()) {
                System.out.println(rs.getString("username"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            TestDBCP.release(conn,rs,st);
        }


    }


}

无论是使用什么数据源 ,本质还是一样,DataSource的接口是不会变的。方法就不会变(获取连接)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值