JDBC API

一、JDBC

1、JDBC的概念

Java DataBase Connectivity

​ JDBC是官方(sun公司)定义的一套操作所有关系型数据库的接口,厂商实现这套接口(数据库驱动jar包)。

2、API
1、注册驱动
2、获取数据库连接对象 Connection
3、定义sql
4、获取执行sql语句的对象 Statement,Pre(防止sql注入,预处理对象)
5、执行sql,接受返回结果
6、处理结果(封装到对象中等)
7、释放资源
// 底层API使用规范。学会封装 | 使用工具

// 注册驱动
Class.forName("com.mysql.jdbc.Driver");

// 获取连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db_temp", "root", "root");

// 定义sql语句
String sql = "update account set xx = xx where id = 1";

// 获取执行sql的对象 Statement
Statement stmt = conn.createStatement(); 

// 执行sql,操作影响行数
int count = stmt.executeUpdate(sql);  

// 处理判断
assert count > 0;

// finally,release,must
stmt.close();
conn.close();
3、小demo
Statement stmt = null;
Connection conn = null;
try {
    Class.forName("com.mysql.jdbc.Driver");

    String sql = "insert into account values('王五',3000)";

    conn = DriverManager.getConnection("jdbc:mysql:///db_temp", "root", "root");

    stmt = conn.createStatement();

    int count = stmt.executeUpdate(sql);  // 返回值为:操作影响的行数

    //6.处理结果
    assert count > 0;
    System.out.println(count);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (SQLException e) {
    e.printStackTrace();
}finally {
    //stmt.close();
    //7. 释放资源
    //避免空指针异常
    if(stmt != null){
        try {
            stmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    if(conn != null){
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
4、API说明
4.1、连接和执行对象
// DriverManager:获取数据库连接对象

// Connection:数据库连接对象,获取执行sql语句的对象,事物管理

//-------------事物控制--------------
conn.setAutoCommit(boolean autoCommit) //关闭自动事务管理
conn.commit() 
conn.rollback() 

//------------sql执行对象
Statement createStatement();
PreparedStatement prepareStatement(String sql);  // 解决sql注入

// 执行sql的方法
boolean execute(String sql);  // 可以执行任意的sql 了解 

// 增删改操作
int executeUpdate(String sql);  // 执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句

// 查操作
ResultSet executeQuery(String sql);  // 执行DQL(select)语句
4.2、获取查询结果集
// 执行sql语句,返回结果集

ResultSet  // 结果集的封装
boolean next()  // 结果集遍历的方法

while(rs.next()){  // 有下一行数据:返回true

    int id = rs.getInt(1);  // 数据和类型对应上
    String name = rs.getString("name");
    double balance = rs.getDouble(3);

    System.out.println(id + "---" + name + "---" + balance);
}
5、解决sql注入问题

​ 利用sql中的一些语法规则、特殊符号让服务器跳过(忽略)对某一部分数据的校验。

select * from user where name = +' + 变量 + ' + and password = +'+ 变量 +';
输入变量 = 哈哈'or 1 = 1  --
select * from user where name = '哈哈' or 1 = 1  --' + and password = +'+ 变量 +';

//----------解决方式--------------
// 使用PreparedStatement对象来解决
	// 预编译的SQL:参数使用?作为占位符

// 见事务控制部分
6、结果封装

查询操作,得到到一行一行的结果集。

// 定义User类:实体类(类名、属性名和数据库名、字段名对应)
// public List<User> findAll(){}
	// 实体类对象userObj
	// 查询数据集合,ResultSet
	// 字段遍历,赋值给实体类对象,userObj.setName(re.getString("name"))
// 实现方法 select * from user;
List<User> list = new List<User>;  // 全局·集合

while(rs.next()){ 
	User obj = new User();  // 实体类对象
    
    // 获取数据
    int id = rs.getInt(1);  // index
    String name = rs.getString("name");  // or fieldName
    double balance = rs.getDouble(3);
    
    // 封装数据
    obj.setId(id);
    obj.setName(name);
    obj.setBalance(balance);
	
    System.out.println(obj); // toString方法
    
    // 对象放到集合中
    list.append(obj);
}
// 循环结束,数据封装完成
// 遍历集合:增强for

二、冗余封装

1、封装工具类

​ 将数据库信息封装到一个配置文件中,通过类加载器进行解析,完成数据库配置,对外提供一个返回数据库连接的方法。

public class JDBCUtils {
	private static String url;
	private static String user;
	private static String password;
	private static String driver;

// 静态代码块:类初始化仅仅加载一次。(静态变量、父类非静态、父类静态代码块、父类构造、子···)
static{
    try {
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();  // 类加载器获取配置文件
		   
            // properties文件  Java文件式式数据结构
            URL res  = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            System.out.println(path);
        
		   // Properties集合类
            Properties pro = new Properties();
            pro.load(new FileReader(path));

            // 获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");

            // 注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
	}

    // 对外提供一个方法,调用方法返回数据库连接conn
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);  // 返回:conn
    }
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        // 资源释放,可能没有Result,但是Statement、Connection都有,可以使用方法重载(参数不同)
    }
}
Connection conn = JDBCUtils.getConnection();
2、释放资源(完善)

​ 调用工具类中的释放资源的方法(释放结果对象、sql执行对象、数据库连接对象)

// 调用使用方式
JDBCUtils.close(null, stmt, conn) // DML(增删改)操作,没有查询结果集
JDBCUtils.close(rs, stmt, conn)  // 查询操作,关闭结果集、语句查询、连接

// 具体实现
public class JDBCUtils {
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

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

三、事物控制

​ 一般的都是基于同一个conn,如果涉及到多个服务(多个数据库):查看分布式事务管理。复习MySQL事务部分。

1、说明
// 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。

// 使用Connection对象来管理事务
	// 开启事务:
	setAutoCommit(false);  // 手动
	
	// sql语句

	// 提交事务:
     commit();
	// 回滚事务:
	rollback();  // 在catch中回滚事务
2、小案例(防止sql注入)
public class JDBCDemo10 {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;

        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            
            //开启事务
            conn.setAutoCommit(false);

            String sql1 = "update account set balance = balance - ? where id = ?";

            String sql2 = "update account set balance = balance + ? where id = ?";

            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);

            pstmt1.setDouble(1, 500);
            pstmt1.setInt(2, 1);

            pstmt2.setDouble(1, 500);
            pstmt2.setInt(2, 2);

            pstmt1.executeUpdate();
            
            // 手动制造异常
            int i = 3 / 0;

            pstmt2.executeUpdate();
            //提交事务
            conn.commit();
            
        } catch (Exception e) {
            //事务回滚
            try {
                if (conn != null) {
                    conn.rollback();
                }
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JDBCUtils.close(null, pstmt1, conn);
        }
    }
}

四、数据库连接池

​ 高效执行

1、连接池接口
// 数据库厂商实现该接口
public interface DataSource{
	// 取出连接对象,厂商实现
	getConnection();
	// 归还对象直接调用
	close();
}
2、C3P0数据库连接池

注意C3P0版本和MySQL版本,以及JDBC-url配置

// 第三方:导入2个jar包
// 定义配置文件(名字固定放到src下)
// 创建核心对象
// 获取连接getConnection();
2.1、实现配置
// 文件名字:c3p0-config.xml
<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
  	<!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db_temp?&amp;useSSL=false&amp;serverTimezone=UTC</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <!--初始化申请的连接数量-->
    <property name="initialPoolSize">5</property>
    <!--最大的连接数量-->
    <property name="maxPoolSize">10</property>
    <!--超时时间-->
    <property name="checkoutTimeout">3000</property>
  </default-config>

  <named-config name="otherc3p0"> 
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db3?&amp;useSSL=false&amp;serverTimezone=UTC</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>
</c3p0-config>
2.2、实现代码
public class C3P0Demo2 {

    public static void main(String[] args) throws SQLException {
        // 获取DataSource,使用默认配置
        DataSource ds  = new ComboPooledDataSource();
      
        for (int i = 1; i <= 11 ; i++) {
      		// 获取连接
            Connection conn = ds.getConnection();
            System.out.println(i+":"+conn);

            if(i == 5){
                // 归还连接到连接池中
                conn.close();
            }
        }
    }
3、Druid数据库连接池
// 导入jar包
// 配置文件:Properties,名字任意,路径任意,手动加载
// 获取数据库连接池对象:工厂
// 获取连接getConnection();
3.1、配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.3.3:33306/Demo1
username=root
password=121388
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
3.2、maven坐标
<!--版本搜索一波-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version></version>
</dependency>
3.3、代码
public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //1.导入jar包
        //2.定义配置文件
        //3.加载配置文件
        Properties pro = new Properties();
        InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        //4.获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        //5.获取连接
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }
}

五、JdbcTemapate

学会使用工具

1、针对连接池设计出来的
/*
* 参数:一个数据库连接池对象DataSource
* 返回值:数据库连接对象Connection
* 方法封装:基础的CRUD,有JdbcTUserlate对象调用
* 方法参数:sql语句,sql参数,封装结果集的RowMapper对象(自定义)
* 优化:自动释放资源(close)
*/
2、代码
public class JdbcTUserlateDemo1 {
    public static void main(String[] args) {
        // 带入jar包
        // 创建JdbcTUserlate对象, 把连接池传过来
        JdbcTUserlate jdbctUserlate = new JdbcTUserlate(JDBCUtils.getDataSource());

        // 生成sql
        String sql = "select * from fruit";
        // 执行方法
        Object list = (Object)jdbctUserlate.queryForList(sql);
        // 自动释放资源,自动归还连接到连接池
        System.out.println(list);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值