JDBC学习

概念:java database connectivity,java连接数据库

  • JDBC实质:官方定义了操作所有关系型数据库的规则(接口)。各个数据库厂商实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
coder--->java代码(jdbc接口)--->数据库驱动(mysql db2 oracle)--->mysql db2 oracle

快速入门

  • 步骤
    1.导入驱动jar包
    2.注册驱动
    3.获取数据库连接对象 Connection
    4.定义sql
    5.获取执行sql语句的对象statement
    6.执行sql,接收结果
    6.处理数据
    7.释放资源
  • 代码实现
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/panda?serverTimezone=UTC","root","123456");
        String sql = "select * from company where company_id < 10";
        Statement stat = conn.createStatement();
        ResultSet resultSet = stat.executeQuery(sql);
        while (resultSet.next()){
            System.out.println(resultSet.getString("name"));
        }
        stat.close();
        conn.close();

详解各个对象

    1.DriverManager:驱动管理对象
    - 功能:
        1)注册驱动
            static void registerDriver(Driver driver)
            写代码:Class.forName("com.mysql.jdbc.Driver");
            通过查看源码得知:在com.mysql.jdbc.Driver类中存在静态代码块
            static {
                try{
                    java.sql.DriverManager.registerDriver(new Driver());
                }catch(SQLException E){
                    //...
                }
            }
            注意:
            msqyl5之后可以不注册驱动,在META-INF==>services==>java.sql.Driver 自动注册了。
        2)获取数据库的连接
            方法:static Connection getConnenction(String url,String user,String password)
            参数:url=>指定连接的路径=>语法:jdbc:mysql://ip:port/databaseName
            例子:jdbc:mysql://localhost:3306/db3
            如果连接是本机的,端口号是3306,则可以缩写:jdbc:mysql:///databaseName
    2.Connection:数据库连接对象
    - 功能:
        1)获取执行sql的对象
            Statement createStatement()
            PreparedStatement prepareStatement(String sql)
        2)管理事务
            开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
            提交事务:commit()
            回滚事务:rollback()
    3.Statement:执行静态sql的对象
        boolean execute(String sql):
                可以执行任意的sql
        int excuteUpdate(String sql):
                可以执行DML(insert,update,delete)、DDL(create,alter,drop)
                返回值:影响的行数,可以通过返回值来检验DML是否执行成功,返回值>1则执行成功。
        ResultSet executeQuery(String sql):
                执行DQL(select)
    4.ResultSet:结果集对象,封装查询对象
        next():游标向下移动一个位置
        getXxx(参数):获取数据
            Xxx是数据类型
            参数:int:代表列的序号;String:代表列的名称
        注意:游标下移=>判断当前行是否最后一行末尾=>获取数据
    5.PreparedStatement:执行动态sql的对象
        SQL注入问题:在拼接sql时,有一些特殊sql的特殊关键字拼接,会造成安全问题
            sql:select * from table where username='xxx' and password='a' or 'a'='a'
        解决注入问题:使用ProparedStatement来解决
            预编译sql:参数使用?作为占位符

抽取JDBC工具类

  • 目的:简化书写
  • 分析:
1.注册驱动也抽取
2.抽取一个方法获取连接对象
    - 配置文件的方法:jdbc.properties
    password=123456
    name=root
    url=jdbc:mysql://localhost:3306/panda?serverTimezone=UTC
    driver=com.mysql.jdbc.Driver
    - 静态代码块来获取配置文件
    static{
        try{
            Properties pro = new Properties();
            //没有初始化所以不能使用下面的方法获取配置文件 ==> pro.load(this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"));
            pro.load(new FileReader(JdbcUtil1.class.getClassLoader().getResource("jdbc.properties").getPath()));
            url = pro.getProperty("url");
            name = pro.getProperty("name");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
        }catch(Exception){}    
    }
    - 获取Connection对象
        Connection connection = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, name, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
3.抽取一个方法释放资源
4.完整代码:
package test.jdbc;

import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtil1 {
    private static String url;
    private static String name;
    private static String password;
    private static String driver;

    static {
        try {
            Properties pro = new Properties();
            //没有初始化所以不能使用下面的方法获取配置文件 ==> pro.load(this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"));
            pro.load(new FileReader(JdbcUtil1.class.getClassLoader().getResource("jdbc.properties").getPath()));
            url = pro.getProperty("url");
            name = pro.getProperty("name");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, name, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    public static void closeConnection(Statement statement, Connection connection) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

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

}

使用JDBC控制事务

  • 事务:一个包含多个业务的操作。如果这个业务操作被事务管理,那么这些多个步骤要么同时成功,要么同时失败。
  • 操作:
    1.开启
    2.提交
    3.回滚
  • 使用Connection对象来管理事务
    开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
        在写sql之前开启事务
    提交事务:commit()
        当所有sql语句执行完之后提交事务
    回滚事务:rollback()
        在catch中回滚事务
  • 代码
@Test
    public void test3() {
        Connection connection = JdbcUtil1.getConnection();
        Statement statement = null;
        //设置为false,开启事务
        try {
            connection.setAutoCommit(false);
            statement = connection.createStatement();
            int index = statement.executeUpdate("update company set name = '小米科技有限责任公司' where company_id = 1");
            int i = 3/0;
            System.out.println(index);
            //提交事务
            connection.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                //回滚事务
                connection.rollback();
            } catch (SQLException e1) {
            }
        } finally {
            JdbcUtil1.closeConnection(statement, connection);
        }

    }

数据库连接池

  • 概念:其实就是一个容器集合,存放数据库连接的容器。当系统初始化好,容器被创建,容器会申请一些连接对象,当用户来访问数据库时,从容器中获取数据库连接对象,用户访问完之后,会将连接对象归还给容器。
  • 好处:节约资源;用户访问效率高
  • 实现:
标准接口:
   DataSource javax.sql包下的
   方法:获取连接getConnection()
        归还连接如果是从Connection池中获得的Connection,用Connection.close(),则归还连接,而不是释放 
一般我们不需要实现它:
   C3P0:数据库连接池技术
   Druid:数据库连接池技术,阿里巴巴实现
  • C3P0:
1.导入jar包(两个): c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar mysql驱动包也得导入
2.定义配置文件:c3p0.properties or c3p0-config.xml
3.创建核心对象 数据库连接对象 ComboPooledDataSource
4.获取连接:getConnection()
--代码:
配置文件:c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!--默认配置-->
    <default-config>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
    </default-config>

    <!--配置连接池mysql-->
    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/panda?serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
    </named-config>
</c3p0-config>
工具类:C3p0Util.java
package test.jdbc;

import com.mchange.v2.c3p0.ComboPooledDataSource;

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

public class C3p0Util {
    static ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");

    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void closeConnection(Statement statement, Connection connection, ResultSet resultSet) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

-测试
        Connection conn = C3p0Util.getConnection();
        Statement statement = conn.createStatement();
        int index = statement.executeUpdate("update company set name = '小米' where company_id = 1");
        System.out.println(index);
        C3p0Util.closeConnection(statement, conn, null);
  • Druid:
-- 步骤
1.导入jar包(两个): druid-1.0.9.jar mysql驱动包也得导入
2.定义配置文件:是properties形式的;可以是任意名称任意目录下
3.加载配置文件。properties
4.创建核心对象 通过工厂类获取的  DruidDataSourceFactory   
5.获取连接:getConnection()

-- 定义工具类
1.定义一个类 JDBCUtils
2.提供静态代码块加载配置,初始化连接池对象
3.提供方法
    1)获取连接的方法:通过连接池获取连接
    2)释放资源
    3)获取连接池的方法

Spring JDBC

* Spring对JDBC的简单封装。提供了一个JDBC的template对象简化开发
* 步骤
1.导入jar包
2.创建JDBCTemplate对象。依赖于数据源DataSource
    - JdbcTemplate template = new JdbcTemplate(ds);
3.调用JdbcTemplate的方法完成CRUD的操作
    - update():DML语句
    - queryForMap():将一条结果的列名作为key,值作为value,封装成map集合
    - queryForList():将多条结果的列名作为key,值作为value,封装成map集合的list
    - query():
        List<Student> list  = template.query(sql,new BeanPropertyRowMapper<Student>(Student.class));
    - queryForObject():查询结果将结果封装成对象
原文地址:https://www.cnblogs.com/yejiang/p/11794824.html