连接池+事务

事务的四个特性:

  1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

   2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

   3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

   4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

事务的4种隔离级别(mysql   默认为读未提交)

   1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

   2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

     3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

 

丢失更新

  定义:事务T1读取了数据,并执行了一些操作,然后更新数据。事务T2也做相同的事,则T1和T2更新数据时可能会覆盖对方的更新,从而引起错误。

《1》  共享锁             lock in share mode    (可能会产生死锁)

1    悲观锁“          《2》  排它锁  (我读的时候你不能读)     select  *  from  user    for    update                                 关键词    for   update

  丢失跟新:

2     乐观锁           加时间戳 每次执行操作的时候去和时间戳比较

  乐观锁  用在丢失更新频率低的情况下       悲观锁用在丢失更新频率高的情况下。

连接池:

1  自定义连接池:

创建连接池

package com.rl.lianjiechi;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.sql.DataSource;

import com.rl.JDBCUtil;

public class MyPool implements DataSource{
	int size;
	LinkedList<Connection> linkedList=new LinkedList<>();

	public MyPool(int size) {
		super();
		this.size = size;
		for(int i=0;i<size;i++){
			try {
				linkedList.add(JDBCUtil.getConnection());
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@Override
	public PrintWriter getLogWriter() throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
		// TODO Auto-generated method stub

	}

	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
		// TODO Auto-generated method stub

	}

	@Override
	public int getLoginTimeout() throws SQLException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Connection getConnection() throws SQLException {
		Object obj=null;
		if(linkedList.size()>0){
			Connection conn = linkedList.removeFirst();
			obj = Proxy.newProxyInstance(conn.getClass().getClassLoader(), new Class[]{com.mysql.jdbc.Connection.class}, new InvocationHandler() {

				@Override
				public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {
					// TODO Auto-generated method stub
					if(!method.getName().equals("close")){
						return method.invoke(conn, args);
					}
					else{
						linkedList.add(conn);
						return null;
					}

				}});
			return (Connection) obj;

		}
		return null;
	}

	@Override
	public Connection getConnection(String username, String password) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

}

  测试类:

package com.rl.lianjiechi;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import com.domain.login.entity.User;
import com.mysql.jdbc.PreparedStatement;

public class Test {
	public static void main(String[] args) throws SQLException {
		Connection conn=null;
		PreparedStatement pst=null;
		MyPool myPool=new MyPool(10);
		conn=myPool.getConnection();
		String sql="select * from user";
		pst=(PreparedStatement) conn.prepareStatement(sql);

		boolean f=pst.execute();
		System.out.println(f);
	}
}

  创建初始化时的连接所用的工具类:

package com.rl;

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

public final class JDBCUtil {
    private static String driver="com.mysql.jdbc.Driver";
    private static String url="jdbc:mysql://localhost:3306/mytest";
    private static String user="root";
    private static String password="123456";

    private JDBCUtil(){}

    static {
        /**
         * 驱动注册
         */
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            throw new ExceptionInInitializerError(e);
        }

    }

    /**
     * 获取 Connetion
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(url, user, password);
    }

    /**
     * 释放资源
     * @param conn
     * @param st
     * @param rs
     */
    public static void colseResource(Connection conn,Statement st,ResultSet rs) {
        closeResultSet(rs);
        closeStatement(st);
        closeConnection(conn);
    }

    /**
     * 释放连接 Connection
     * @param conn
     */
    public static void closeConnection(Connection conn) {
        if(conn !=null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //等待垃圾回收
        conn = null;
    }

    /**
     * 释放语句执行者 Statement
     * @param st
     */
    public static void closeStatement(Statement st) {
        if(st !=null) {
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //等待垃圾回收
        st = null;
    }

    /**
     * 释放结果集 ResultSet
     * @param rs
     */
    public static void closeResultSet(ResultSet rs) {
        if(rs !=null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //等待垃圾回收
        rs = null;
    }
}

  

2常见的几种数据源

  传递给JDBC驱动的用于连接数据库的用户名、密码、URL以及驱动类名。

  DBCP c3p0 Druid
用户名 username user username
密码 password password password
URL url jdbcUrl jdbcUrl
驱动类名 driverClassName driverClass driverClassName

注:在Druid连接池的配置中,driverClassName可配可不配,如果不配置会根据url自动识别dbType(数据库类型),然后选择相应的driverClassName。

  关键配置:为了发挥数据库连接池的作用,在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数 据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池 请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

  最小连接数:

  是数据库一直保持的数据库连接数,所以如果应用程序对数据库连接的使用量不大,将有大量的数据库资源被浪费。

  初始化连接数:

  连接池启动时创建的初始化数据库连接数量。

  最大连接数:

  是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求被加入到等待队列中。

  最大等待时间:

  当没有可用连接时,连接池等待连接被归还的最大时间,超过时间则抛出异常,可设置参数为0或者负数使得无限等待(根据不同连接池配置)。

  DBCP c3p0 Druid
最小连接数 minIdle(0) minPoolSize(3) minIdle(0)
初始化连接数 initialSize(0) initialPoolSize(3) initialSize(0)
最大连接数 maxTotal(8) maxPoolSize(15) maxActive(8)
最大等待时间 maxWaitMillis(毫秒) maxIdleTime(0秒) maxWait(毫秒)

c3p0配置如下:

该文件应命名为c3p0-config.xml放在类路径下。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <c3p0-config>
  3. <!-- This is default config! -->
  4. <default-config>
  5. <property name="initialPoolSize">10</property>
  6. <property name="maxIdleTime">30</property>
  7. <property name="maxPoolSize">100</property>
  8. <property name="minPoolSize">10</property>
  9. <property name="maxStatements">200</property>
  10. </default-config>
  11. <!-- This is my config for mysql-->
  12. <named-config name="mysql">
  13. <property name="driverClass">com.mysql.jdbc.Driver</property>
  14. <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF8</property>
  15. <property name="user">root</property>
  16. <property name="password"></property>
  17. <!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3-->
  18. <property name="initialPoolSize">10</property>
  19. <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 -->
  20. <property name="maxIdleTime">30</property>
  21. <!--连接池中保留的最大连接数。默认值: 15 -->
  22. <property name="maxPoolSize">100</property>
  23. <!-- 连接池中保留的最小连接数,默认为:3-->
  24. <property name="minPoolSize">10</property>
  25. <!--c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效,只要有一个不为0,则语句的缓存就能生效。如果默认值: 0-->
  26. <property name="maxStatements">200</property>
  27. <!-- 当连接池连接耗尽时,客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。默认: 0 -->
  28. <property name="checkoutTimeout" value="3000"/>
  29. <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 -->
  30. <property name="acquireIncrement" value="2"/>
  31. <!--定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次-->
  32. <property name="acquireRetryAttempts" value="0"/>
  33. <!--重新尝试的时间间隔,默认为:1000毫秒-->
  34. <property name="acquireRetryDelay" value="1000" />
  35. <!--关闭连接时,是否提交未提交的事务,默认为false,即关闭连接,回滚未提交的事务 -->
  36. <property name="autoCommitOnClose">false</property>
  37. <!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试使用。默认值: null -->
  38. <property name="automaticTestTable">Test</property>
  39. <!--如果为false,则获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常,但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认: false-->
  40. <property name="breakAfterAcquireFailure">false</property>
  41. <!--每60秒检查所有连接池中的空闲连接。默认值: 0,不检查 -->
  42. <property name="idleConnectionTestPeriod">60</property>
  43. <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。默认值: 0 -->
  44. <property name="maxStatementsPerConnection"></property>
  45. </named-config>
  46. <!-- This is my config for oracle -->
  47. <named-config name="oracle">
  48. <property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
  49. <property name="jdbcUrl">jdbc:oracle:thin:@localhost:1521:orcl</property>
  50. <property name="user">scott</property>
  51. <property name="password">liang</property>
  52. <property name="initialPoolSize">10</property>
  53. <property name="maxIdleTime">30</property>
  54. <property name="maxPoolSize">100</property>
  55. <property name="minPoolSize">10</property>
  56. <property name="maxStatements">200</property>
  57. </named-config>
  58. </c3p0-config>

原文地址:https://www.cnblogs.com/MyJavaStudy/p/9202662.html

时间: 2024-10-11 01:54:00

连接池+事务的相关文章

Java实战之04JavaWeb-05事务和连接池

一.事务部分 1.事务的简介 做一件事情,这个一件事情中有多个组成单元,这个多个组成单元要不同时成功,要不同时失败.A账户转给B账户钱,将A账户转出钱的操作与B账户转入钱的操作绑定到一个事务中,要不这两个动作同时成功,代表这次转账成功,要不就两个动作同时失败,代表这次转账失败. 2.mysql的事务控制 mysql默认事务是自动提交的,一条sql是一个事务 手动开启事务:start transaction 当手动开启事务后,数据库默认的事务的自动提交暂时失效 提交事务:commit 提交事务到开

SpringMVC+Spring+Mybatis整合,使用druid连接池,声明式事务,maven配置

一直对springmvc和mybatis挺怀念的,最近想自己再搭建下框架,然后写点什么. 暂时没有整合缓存,druid也没有做ip地址的过滤.Spring的AOP简单配置了下,也还没具体弄,不知道能不能用,log也不知道能不能用,`(*∩_∩*)′哈哈,有点不负责任...... 直接上代码: 使用的eclipse和eclipse自带的maven,参考了网上的资料,有些代码是拷贝的,不过都自己测试过了.嗯,可以跑起来... 先上项目结构: 新建maven项目,选择web,然后配置pom: <pro

JAVAWEB开发之事务详解(mysql与JDBC下使用方法、事务的特性、锁机制)和连接池的详细使用(dbcp以d3p0)

事务简介 事务的概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功 在开发中,有事务的存在,可以保证数据的完整性. 注意:数据库默认事务是自动提交的,也就是发一条SQL 就执行一条.如果想多条SQL语句放在一个事务中执行,需要添加事务有关的语句. 如何开启事务? 事务的操作方式: 创建表: create table account( id int primary key auto_increment, name varchar(20), money double

连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法

本文出处:http://www.cnblogs.com/wy123/p/6110349.html 之前遇到过这么一种情况: 连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持续较长时间,有时间持续时间较短,没有什么规律.  之后分析相关存储过程和代码写法,发现是存储过程中开启了事务,而应用程序在调用存储过程发生异常之后没有进行特别的处理(提交或者回滚),  那么在执行方法发生异常之后,连接关闭了,但是数据库中遗留有活动事务(dbcc opentran对应的Session

Spring Boot1.5.4 连接池 和 事务

原文:https://github.com/x113773/testall/issues/10 默认连接池---spring Boot中默认支持的连接池有Tomcat.HikariCP .DBCP .DBCP2,以下摘自[官方文档](http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-configure-datasource):> Production database

JavaWeb系列之十三(jdbc事务与连接池)

 1.事务:表示一组操作要么都成功,有一个失败,所有操作都会失败. 在mysql要使用事务,就要先开启事务,语句start transaction,提交事务:commit 回滚事务:rollback. 转账: 2.jdbc事务的操作 (1)操作事务的方法 setAutoCommit(boolean autoCommit) 设置事务的提交方式,默认自动提交,设置为fals不会提交 提交事务commit() 回滚事务rollback() 使用jdbc来完成转账 小金跟小李接一千 (2)设置事务的

day18(JDBC事务&连接池介绍&DBUtils工具介绍&BaseServlet作用)

day18总结 今日思维导图: 今日内容 事务 连接池 ThreadLocal BaseServlet自定义Servlet父类(只要求会用,不要求会写) DBUtils à commons-dbutils ? 事务 ? 事务的四大特性:ACID: mysql中操作事务 jdbc中操作事务 ? ? ? 事务概述 为了方便演示事务,我们需要创建一个account表: CREATE TABLE account( ????id INT PRIMARY KEY AUTO_INCREMENT, ????NA

6.事务 连接池

事务 事务介绍: 就是一件事情,操作要不全部成功,要不全部失败. mysql里的事务操作 通过一个命令(show variables like 'autocommit';) 得到 autocommit=on;意思是事务 都自动提交 每一条sql都是一个事务 手动事务的操作:(☆) start transaction; 开始事务(不管是否自动提交) commit;提交事务 rollback;事务回滚 通过以下命令,可以设置事务为手动提交 set autocommit=off; 注意:一旦设置手动提

网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2次. >强烈依赖数据库的驱动jar 解决办法: Class.forName("com.mysql.jdbc.Driver"); 1.1.2 API详解:java.sql.Statement接口: 操作sql语句,并返回相应结果 String sql = "某SQL语句&qu