笔记:JDBC(二)——批处理/事务/连接池
一、批处理
概念:将向数据库表一次性插入多条记录,而不是一条一条插入的方式,这样可以提供效率。
实现方法:
- Statement批处理,该类提供如下方法用于批处理操作。
方法摘要 |
|
|
|
|
|
|
|
- PreparedStatement批处理,该类提供如下方法用于批处理操作。
方法摘要 |
|
|
|
- start transaction命令:表示开启事务。
- rollback命令:表示回滚事务。如果选择回滚事务的话,数据将恢复到事物开启之前的状态。
- commit命令:表示提交事务。如果选择提交事务的话,数据更新之后将无法恢复。
上面是在MySQL数据库中管理事务,在实际开发中,更多是在Java代码中管理MySQL的事务。也就是说,是利用JDBC来管理MySQL事务。JDBC提供如下三种方法来管理MySQL事务:
方法摘要 |
|
|
|
|
|
|
|
MySQL事务的回滚操作,默认是回滚到开启事务之前的数据状态。但在实际开发中,经常需要数据回滚到某个指定的执行状态。MySQL提供了回滚点(Savepoint)的概念,回滚点类似于游戏中的存档。也就是说,设置回滚点后,可以将事务回滚到指定某个回滚点的数据状态。下表是回滚点提供的相关方法:
方法摘要 |
|
|
|
|
|
|
|
|
在日常MySQL的事务管理中,如果多线程开启各自事务操作,而数据库不负责隔离操作时,经常会出现以下三种常见问题:
- 脏读:指一个事务读取到另一个事务未提交的数据记录。
脏读这种操作在实际是非常危险的。例如如果B给A转账10000元钱,B开启一个事务用于转账10000元,实际操作后并未提交事务。如果此时A查询自己的账户会发现已经收到B转账的10000元,当A做出实际动作(发货)后,B再将事务回滚,最终导致A损失10000元钱。
- 不可重复读:指一个事务中读取指定表中的某一条数据,多次读取结果不同。
例如如果A第一次查询账户为20000元钱后,B向A转账10000元钱,A在第二次查询账户为30000元钱。前后两次查询结果不一致,A可能不知道多出的10000元钱是来自哪里。
不可重复读与脏读的区别在于脏读读取的是前一事务未提交的数据,而不可重复读读取的是前一事务提交的数据。
- 幻读(虚读):指一个事务中读取到另一个事务插入的数据,导致前后读取结果不一致。
例如酒店统计房间预订数量时,第一次统计为101间被预订,A在酒店第一次统计后,预订了110房间,酒店在A成功预订110房间后第二次统计,结果为102间被预订。导致酒店前后统计数量不一致。
幻读与不可重复读的区别在于不可重复读读取的是另一个事务的更新操作,而幻读读取的是另一个事务的插入操作(MySQL数据库无法测试到幻读问题)。
针对上述的三个问题,MySQL数据库提供了四大隔离级别来解决,这四大隔离级别分别为:
- SERIALIZABLE(串行化)
这个隔离级别可避免脏读、不可重复读、虚读情况的发生。
- REPEATABLE READ(可重复读)
这个隔离级别可避免脏读、不可重复读情况的发生。
- READ COMMITTED(读已提交数据)
这个隔离级别可避免脏读情况发生。
- READ UNCOMMITTED(读未提交数据)
这个隔离级别最低级别,以上情况均无法保证。
- 四个隔离级别的优先级:
SERIALIZABLE –> REPEATABLE READ -> READ COMMITTED -> READ UNCOMMITTED
- 四个隔离级别的性能:
READ UNCOMMITTED -> READ COMMITTED -> REPEATABLE READ -> SERIALIZABLE
连接池可以极大的改善用户的 Java 应用程序的性能,同时减少全部资源的使用。连接池主要的优点有:
- 减少连接创建时间。
- 简化的编程模式。
- 受控的资源使用。
DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目。单独使用dbcp需要3个包:commons-dbcp.jar,commons-pool.jar,commons-collections.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。
2、C3P0
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。
C3P0与DBCP的区别:
dbcp没有自动回收空闲连接的功能。
c3p0有自动回收空闲连接功能。
3、JNDI
NDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI API的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。集群JNDI实现了高可靠性JNDI,通过服务器的集群,保证了JNDI的负载平衡和错误恢复。在全局共享的方式下,集群中的一个应用服务器保证本地JNDI树的独立性,并拥有全局的JNDI树。每个应用服务器在把部署的服务对象绑定到自己本地的JNDI树的同时,还绑定到一个共享的全局JNDI树,实现全局JNDI和自身JNDI的联系。
JNDI(Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。
JNDI(Java Naming and Directory Interface)是允许将一个Java对象绑定到一个JNDI容器(tomcat)中 ,并且为对象指定一个名称,通过javax.naming 包 Context 对JNDI 容器中绑定的对象进行查找,通过指定名称找到绑定Java对象。