1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
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;
}
}
| DBCP | c3p0 | Druid | |
| 用户名 | username | user | username |
| 密码 | password | password | password |
| URL | url | jdbcUrl | jdbcUrl |
| 驱动类名 | driverClassName | driverClass | driverClassName |
| 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放在类路径下。
原文:https://www.cnblogs.com/MyJavaStudy/p/9202662.html