day29:连接池,事务,锁,视图

文章介绍了C3P0作为连接池的使用,包括配置、工具类编写及使用示例。此外,还讨论了事务的概念、MySQL的事务操作和事务的ACID特性。同时,提到了并发访问时可能出现的问题和不同隔离级别的解决方案,以及锁的类型和作用。最后,文章简述了视图在数据安全和简化查询中的优势与潜在缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常见的连接池:C3P0、DRUID。

C3P0连接池工具类编写

C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用C3P0连接池需要导入jar包,c3p0使用时还需要添加配置文件“c3p0-config.xml”

使用步骤

  1. 添加jar包

  2. 编写配置文件 c3p0-config.xml,放在src中(注:文件名一定不要写错)

  3. 编写工具类

编写C3P0工具类

/*
     javax.sql.DataSource  连接池接口
           方法
              Connection getConnection()
              只要使用连接池对象 调用getConnection方法 就是从连接池中 获取了连接对象
              要想获取连接 必须找到DataSource接口的实现类对象  C3P0实现类这个接口
              对应的实现类是ComboPooledDataSource ,我们只要创建这个类的对象
              调用getConnection方法 就 从连接池中 获取到了连接对象



 */
public class C3P0Utils {

    private static ComboPooledDataSource ds ;

    static{

        try{
             ds = new ComboPooledDataSource();
            //配置连接池的信息
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/day04");
            ds.setUser("root");
            ds.setPassword("root");

        }catch (Exception e){
            throw new RuntimeException(e);
        }


    }

    public static Connection getConnection() throws SQLException, PropertyVetoException {

        Connection con = ds.getConnection();

        return con;

    }


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

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

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

}

C3P0连接池工具类的使用

public class Demo {
	public static void main(String[] args) throws Exception {
		// 拿到连接
		Connection conn = JdbcUtils.getConnection();

		// 执行sql语句
		String sql = "INSERT INTO student VALUES (NULL, ?, ?, ?);";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		pstmt.setString(1, "李四");
		pstmt.setInt(2, 30);
		pstmt.setDouble(3, 50);
		int i = pstmt.executeUpdate();
		System.out.println("影响的函数: " + i);

		// 关闭资源
		JdbcUtils.close(conn, pstmt);
	}
}

事务概述

  • 事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败.

  • 事务作用:保证在一个事务中多次SQL操作要么全都成功,要么全都失败.

mysql事务操作

sql语句描述
start transaction;begin;开启事务
commit提交事务
rollback回滚事务
# 创建一个表:账户表.
create database webdb;
# 使用数据库
use webdb;
# 创建账号表
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double
);
# 初始化数据
insert into account values (null,'jack',10000);
insert into account values (null,'rose',10000);
insert into account values (null,'tom',10000);

 

jdbc事务操作

Connection 对象的方法名描述
conn.setAutoCommit(false)开启事务
conn.commit()提交事务
conn.rollback()回滚事务
//事务模板代码
public void demo01() throws SQLException{
	// 获得连接
	Connection conn = null;
	
	try {
		//#1 开始事务
		conn.setAutoCommit(false);
		
		//.... 加钱 ,减钱
		
		//#2 提交事务
		conn.commit();
	} catch (Exception e) {
		//#3 回滚事务
		conn.rollback();
	} finally{
		// 释放资源
		conn.close();
	}
}

JDBC事务分层(dao、service)传递Connection

  • 开发中,常使用分层思想

    • 不同的层次结构分配不同的解决过程,各个层次间组成严密的封闭系统

  • 不同层级结构彼此平等

  • 分层的目的是:

    • 解耦

    • 可维护性

    • 可扩展性

    • 可重用性

  • 不同层次,使用不同的包表示

    • com.doit 公司域名倒写

    • com.doit.dao dao层

    • com.doit.service service层

    • com.doit.domain javabean

    • com.doit.utils 工具

事务特性:ACID

  • 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

  • 一致性(Consistency)事务前后数据的完整性必须保持一致。

  • 隔离性(Isolation)事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

  • 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

2.2 并发访问问题

如果不考虑隔离性,事务存在3中并发访问问题。

  1. 脏读:一个事务读到了另一个事务未提交的数据.

  2. 不可重复读:一个事务读到了另一个事务已经提交(update)的数据。引发另一个事务,在事务中的多次查询结果不一致。

  3. 虚读 /幻读:一个事务读到了另一个事务已经提交(insert)的数据。导致另一个事务,在事务中多次查询的结果不一致。

隔离级别:解决问题

  • 数据库规范规定了4种隔离级别,分别用于描述两个事务并发的所有情况。

  1. read uncommitted 读未提交,一个事务读到另一个事务没有提交的数据。

    a)存在:3个问题(脏读、不可重复读、虚读)。

    b)解决:0个问题

  2. read committed 读已提交,一个事务读到另一个事务已经提交的数据。

    a)存在:2个问题(不可重复读、虚读)。

    b)解决:1个问题(脏读)

  3. repeatable read:可重复读,在一个事务中读到的数据始终保持一致,无论另一个事务是否提交。

    a)存在:1个问题(虚读)。

    b)解决:2个问题(脏读、不可重复读)

  4. serializable 串行化,同时只能执行一个事务,相当于事务中的单线程。

    a)存在:0个问题。

    b)解决:3个问题(脏读、不可重复读、虚读)

  • 安全和性能对比

    • 安全性:serializable > repeatable read > read committed > read uncommitted

    • 性能 : serializable < repeatable read < read committed < read uncommitted

  • 常见数据库的默认隔离级别:

    • MySql:repeatable read

    • Oracle:read committed

锁分类从对数据库操作的类型分,分为读锁和写锁

  • 读锁(共享锁,S锁(Shared)):针对同一份数据,多个读操作可以同时进行而不会互相影响

  • 写锁(排它锁,X锁(eXclusive)):当前写操作没有完成前,它会阻断其他写锁和读锁

从对数据操作的粒度分,分为表锁和行锁

 每次操作锁住整张表。

 

CREATE TABLE mylock(
	id INT  PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20) 
)ENGINE=MYISAM;
INSERT INTO mylock(NAME) VALUES
('a'),
('b'),
('c'),
('d'),
('e');

  • 手动增加表锁

lock table 表名称 read(write),表名称2 read(write);
  • 查看表上加过的锁

show open tables;
  • 删除表锁

unlock tables;

行锁

每次操作锁住一行数据。

InnoDB与MYISAM的最大不同有两点:

  • InnoDB支持事务(TRANSACTION)

  • InnoDB支持行级锁

索引失效导致行锁变表锁

CREATE TABLE test_innodb(
	id INT PRIMARY KEY AUTO_INCREMENT,
	b VARCHAR(100),
    KEY(b)
);
INSERT INTO test_innodb(b) VALUES
('100'),
('200'),
('500'),
('1000'),
('600'),
('700'),
('800');

update test_innodb set  id = 10 where b = '1000';

update test_innodb set  id = 1000 where b = '800';

锁主要是加在索引上,如果对非索引字段更新,行锁可能会变表锁session1 执行:update test_innodb set id = 10 where b = 1000;session 对该表任一行操作都会阻塞住

在大型项目中,以及数据表比较复杂的情况下,视图的价值就凸显出来了,它可以帮助我们把经常查询的结果集放到虚拟表中,提升使用效率。

CREATE VIEW 视图名称
AS 查询语句
CREATE VIEW v_student AS
SELECT
id,NAME,sex
FROM student t
WHERE id = 901;

SELECT * FROM v_student;

-- 针对别名的处理,可以在创建视图的子查询中指定对应的别名
CREATE VIEW v_student1
AS
SELECT id stu_id,name stu_name,sex gender
FROM student ;
-- 也可以在创建视图的视图名称后添加对应的别名字段
CREATE VIEW v_student2(stu_id,stu_name,gender)
AS
SELECT id ,name ,sex
FROM student ;

视图总结

优点

视图优点解释说明
操作简单将经常使用的查询操作定义为视图,可以使开发人员不需要关心视图对应的数据表的结构、表与表之间的关联关系,也不需要关心数据表之间的业务逻辑和查询条件,而只需要简单地操作视图即可,极大简化了开发人员对数据库的操作。
减少数据冗余视图跟实际数据表不一样,它存储的是查询语句。所以,在使用的时候,我们要通过定义视图的查询语句来获取结果集。而视图本身不存储数据,不占用数据存储的资源,减少了数据冗余。
数据安全MySQL将用户对数据的 访问限制 在某些数据的结果集上,而这些数据的结果集可以使用视图来实现。用户不必直接查询或操作数据表。这也可以理解为视图具有隔离性 。视图相当于在用户和实际的数据表之间加了一层虚拟表
灵活多变当业务系统的需求发生变化后,如果需要改动数据表的结构,则工作量相对较大,可以使用视图来减少改动的工作量。这种方式在实际工作中使用得比较多。
简化复杂查询逻辑数据库中如果存在复杂的查询逻辑,则可以将问题进行分解,创建多个视图获取数据,再将创建的多个视图结合起来,完成复杂的查询逻辑。

缺点

如果我们在实际数据表的基础上创建了视图,那么,如果实际数据表的结构变更了我们就需要及时对相关的视图进行相应的维护。特别是嵌套的视图(就是在视图的基础上创建视图),维护会变得比较复杂, 可读性不好 ,容易变成系统的潜在隐患。因为创建视图的 SQL 查询可能会对字段重命名,也可能包含复杂的逻辑,这些都会增加维护的成本。实际项目中,如果视图过多,会导致数据库维护成本的问题。

所以,在创建视图的时候,你要结合实际项目需求,综合考虑视图的优点和不足,这样才能正确使

用视图,使系统整体达到最优。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值