JDBC(自用)

没有JDBC的时候,如果现在要开发一套系统,使用Java连接MySQL数据库,那么这时候Java程序员需要了解MySQL驱动API,如果使用Java连接Oracle数据库,那么这个时候Java程序员需要了解Oracle数据库驱动API。
SUN公司提供一套统一的规范(接口)。然后各个数据库生产商提供这套接口的实现。这套接口规范就是JDBC的规范。

快速入门

  1. 加载jar驱动包
  2. 获得连接
  3. 基本操作
  4. 释放资源
package t_jdbc;

import jdk.internal.instrumentation.ClassInstrumentation;

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

public class jdbc入门 {
    public static void main(String[] args) throws Exception {
//    注册驱动
    Class.forName("com.mysql.jdbc.Driver");
//    获得连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
//    执行sql
//        获得执行对象
    Statement statement = conn.createStatement();
//            编写sql语句
        String sql = "select * from class";
//            执行sql
        ResultSet rs = statement.executeQuery(sql);
//            遍历结果集
        while (rs.next()){
            System.out.print(rs.getInt("id") + " ");
            System.out.println(rs.getString("name"));
        }

//    释放连接
        rs.close();
        statement.close();
        conn.close();
    }
}

JDBC的API详解

DriverManager(驱动管理类)

  1. 注册驱动
    这个方法可以完成驱动的注册,但是实际开发中一般不会使用这个方法完成驱动的注册!!!
    原因:
    如果需要注册驱动,就会使用DriverManager.registerDriver(new Driver());,但是查看源代码发现,在代码中有一段静态代码块,静态代码块已经调用了注册驱动的方法。如果再手动调用该方法注册驱动,就会导致驱动被注册两次

  2. 获得连接
    getConnection(url,user,password);
    这个方法就是用来获得与数据库连接的方法:这个方法中有三个参数:

url			:与数据库连接的路径
user			:与数据库连接的用户名
password		:与数据库连接的密码

主要关注的是url的写法:

jdbc:mysql://localhost:3306/web_test3
jdbc			:连接数据库的协议
mysql		:是jdbc的子协议
localhost		:连接的MySQL数据库服务器的主机地址。(连接是本机就可以写成localhost),如果连接不是本机的,就需要写上连接主机的IP地址。
3306		:MySQL数据库服务器的端口号
web_test3	:数据库名称

Connection(接口)

连接对象

  1. 创建执行sql语句的对象
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    执行SQL语句对象:
Statement			:执行SQL
CallableStatement		:执行数据库中存储过程
PreparedStatement		:执行SQL.对SQL进行预处理。解决SQL注入漏洞。
  1. 管理事务
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

statement

执行sql

  1. 执行sql语句
执行SQL的方法
boolean execute(String sql);
执行查询,修改,添加,删除的SQL语句。
ResultSet executeQuery(String sql);
执行查询(执行select语句)。
int executeUpate(String sql);
执行修改,添加,删除的SQL语句。

execute 方法执行 SQL 语句如果第一个结果为 ResultSet 对象,则返回 true;如果其为更新计数或者不存在任何结果,则返回 false

  1. 执行批处理
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

resultSet(结果集)

通过select语句的查询结果。

  1. 结果集遍历
  2. 结果集的获取

资源释放

DBC程序执行结束后,将与数据库进行交互的对象释放掉,通常是ResultSet,Statement,Connection。
这几个对象中尤其是Connection对象是非常稀有的。这个对象一定要做到尽量晚创建,尽早释放掉。
将资源释放的代码写入到finally的代码块中。
资源释放的代码应该写的标准:

		if(rs !=null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				rs = null;
			}
			
			if(statement !=null){
				try {
					statement.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				statement = null;
			}
			
			
			if(conn !=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				conn = null;
			}

sql注入漏洞

在早期互联网上SQL注入漏洞普遍存在。有一个网站,用户需要进行注册,用户注册以后根据用户名和密码完成登录。假设现在用户名已经被其他人知道了,但是其他人不知道你的密码,也可以登录到网站上进行相应的操作。

登录功能

String sql = "select * from user where username = ' "+username+" ' and password = ' "+password+" ' ;";
ResultSet rs = statement.executeQuery(sql);
if (rs.next()){
	System.out.println("登录成功");
	return true}

sql注解漏洞

知道用户名
输入
用户名:aaa‘ or '1=1 密码随意
或者用户名:aaa' -- 密码随意

原因

select * from user where username = ' aaa' or '1 = 1 ' and password = ' "+password+" '--在sql语句中表示注释,只执行了前面
select * from user where username = ' aaa' -- ' and password = ' "+password+" ' ;

解决
采用PreparedStatement对象解决。这个对象将SQL预先进行编译,使用?作为占位符。?所代表内容是SQL所固定。再次传入变量(包含SQL的关键字)。这个时候也不会识别这些关键字。

    public static  boolean login(String username, String password) throws Exception {
        boolean flas = false;
        Connection coon = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        Class.forName("com.mysql.jdbc.Driver");
        coon = DriverManager.getConnection("jdbc:mysql:///test","root","root");
        //编写sql语句
        String sql = "select * from user where username = ? and password = ? ";
        //预编译
        pstmt = coon.prepareStatement(sql);
        //设置参数1是第一个?
        pstmt.setString(1,username);
        pstmt.setString(2,password);
        rs = pstmt.executeQuery();

批处理

mysql默认情况下批处理是关闭的需要在url后添加?rewriteBatchedStatements=true参数

 	    Connection coon = null;
        Statement stmt = null;
        Class.forName("com.mysql.jdbc.Driver");
        coon = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
        stmt = coon.createStatement();
        String sql1 = "create table user(id int primary key auto_increment,name varchar(20))";
        String sql2 = "insert user values (null,'kang')";
        String sql3 = "insert user values (null,'wu')";
        String sql4 = "insert user values (null,'xiao')";
        String sql5 = "insert user values (null,'feng')";
        stmt.addBatch(sql1);
        stmt.addBatch(sql2);
        stmt.addBatch(sql3);
        stmt.addBatch(sql4);
        stmt.addBatch(sql5);
        stmt.executeBatch();
        Connection coon = null;
        PreparedStatement stmt = null;
        Class.forName("com.mysql.jdbc.Driver");
        coon = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
        String sql = "insert into usear values (null,?)";
        stmt = coon.prepareStatement(sql);
        for (int i=1;i<100;i++){
            stmt.setString(1,"name" + i);
            stmt.addBatch();
            if(i % 10 == 0 ){
                stmt.executeBatch();
                stmt.clearBatch();
            }
        }

事务

        Connection coon = null;
        PreparedStatement pstm = null;
        Class.forName("com.mysql.jdbc.Driver");
        coon = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
        //开启事务,关闭自动提交
        coon.setAutoCommit(false);
        String sql = "update account set money + ? where name = ?";
        pstm = coon.prepareStatement(sql);
        pstm.setDouble(1,-1000);
        pstm.setString(2,"kang");
        pstm.executeUpdate();
        pstm.setDouble(1,1000);
        pstm.setString(2,"WU");
        pstm.executeUpdate();
        //提交事务
        coon.commit();
        //如果有错,回滚coon.rollback();

连接池

自定义连接池

编写类实现DataSource接口,重写getConnection,初始化多个连接,编写归还方法。

public class jdbc_DataSource implements DataSource {
   //定义集合存储连接对象
   private List<Connection> connList = new ArrayList();

    //初始化获得连接
    public jdbc_DataSource() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        for (int i=1;i<3;i++){
            connList.add(DriverManager.getConnection("","",""));
        }
    }

    @Override
    //从连接池获得连接
    public Connection getConnection() throws SQLException {
        Connection coon = connList.remove(0);
        return coon;
    }
    //编写归还方法
    public void addBack(Connection coon){
        connList.add(coon);
    }
        jdbc_DataSource jd = null;
        Connection coon = null;
        try{
            jd = new jdbc_DataSource();
            coon = jd.getConnection();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            jd.addBack(coon);
        }

Druid连接池

导入jar包

        Connection coon = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;
        //使用连接池
        DruidDataSource dataSource = new DruidDataSource();
        //手动设置参数
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///test");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        //获得连接
        coon = dataSource.getConnection();
        String sql = "select * from test";
        psmt = coon.prepareStatement(sql);
        rs = psmt.executeQuery();

Druid参数可以用属性配置文件的方式配置。文件名没有规定但是属性文件中的key是一定的

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///web_test4?rewriteBatchedStatements=true
username=root
password=abc
        Properties properties = new Properties();
        properties.load(new FileInputStream("src/druid.properties"));
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        coon = dataSource.getConnection();

C3P0连接池

导入jiar包

        Connection coon = null;
        PreparedStatement psmt = null;
        ResultSet rs = null;
        //使用连接池
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //设置参数
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql:///test");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        //获得连接
        coon = dataSource.getConnection();
        String sql = "select * from test";
        psmt = coon.prepareStatement(sql);
        rs = psmt.executeQuery();

设置配置文件c3p0-config.xml

<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql:///test</property>
		<property name="user">root</property>
		<property name="password">root</property>
		
		<property name="initialPoolSize">5</property>
		<property name="minPoolSize">5</property>
		<property name="maxPoolSize">20</property>
	</default-config> 
	
	<!-- This app is massive! -->
<!-- 	<named-config name="oracle">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql:///web_test4</property>
		<property name="user">root</property>
		<property name="password">abc</property>
	</named-config> -->
</c3p0-config>
        //使用连接池,创建连接池会默认去查找c3p0-config.xml文件
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
//        ComboPooledDataSource dataSource = new ComboPooledDataSource("oracle");

Dbutils

对jdbc的简单封装,而且没有影响性能

导入jar包

添加,修改,删除操作

        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //创建核心类
        QueryRunner queryRunner =new QueryRunner(dataSource);
        //添加(insert),修改(update),删除(delete),传入sql和可变参数
        queryRunner.update("insert into test values (null,?,?)","ddd",1000);

查询操作

先创建一个类,存储从数据库查到的数据

public class Account {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

查一条

        //查询,传入sql,ResultHandler一个结果集的接口,可变参数
        Account account = queryRunner.query("select * from test where id = ?", new ResultSetHandler<Account>(){
            @Override
            public Account handle(ResultSet rs) throws SQLException {
                Account account1 =new Account();
                while (rs.next()){
                    account1.setId(rs.getInt("id"));
                    account1.setName(rs.getString("name"));
                }
                return account1;
            }
        },1);

查多条

        queryRunner.query("select * from test", new ResultSetHandler<List<Account>>() {
            @Override
            public List<Account> handle(ResultSet rs) throws SQLException {
                List<Account> list = new ArrayList<>();
                while (rs.next()){
                    Account account1 =new Account();
                    account1.setId(rs.getInt("id"));
                    account1.setName(rs.getString("name"));
                    list.add(account1);
                }
                return list;
            }
        });

ResultSetHandler实现类

ArrayHandler
将一条记录封装到数组当中。这个数组是Object[]
ArrayListHandler
将多条记录封装到装有Object的list集合中

        Object[] objs = queryRunner.query("select * from test where id = ?",new ArrayHandler(),1);
        System.out.println(Arrays.toString(objs));



        List<Object[]> list = queryRunner.query("select * from test",new ArrayListHandler());

BeanHandler将一条记录装到javaBean中
BeanListHandler将多条记录装到一个装有Javabe的list集合中

        Account account1 = queryRunner.query("select * from test where id = ?",new BeanHandler<Account>(Account.class),1);


        List<Account> list1 = queryRunner.query("select * from test",new BeanListHandler<Account>(Account.class));

MapHandler将一条记录封装到一个Map集合中,key是列名,value就是表中列的记录值
MapListHandler装到一个装有Map的list集合中

        Map<String,Object> map = queryRunner.query("select * from test where id = ?",new MapHandler(),1);

        List<Map<String,Object>> list2 = queryRunner.query("select * from test",new MapListHandler());

ColumnListHandler
将数据中的莫列装到list中
ScalarHandler
将单个值封装
KeyedHandler
将一条记录装到一个map中。将多个记录装到一个map集合的map集合中,外面的key可以指定

        List<Object> list3 = queryRunner.query("select * from test",new ColumnListHandler("name"));

        Object o = queryRunner.query("select count(*) from test",new ScalarHandler());

        Map<Object,Map<String,Object>> map1 = queryRunner.query("select * from test",new KeyedHandler("id"));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值