JDBC复习3 20110914

本文介绍了数据库事务的ACID特性及其重要性,探讨了如何使用Java API进行事务管理,并详细解释了四种不同的事务隔离级别及其对并发操作的影响。

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

事务ACID

原子性(atomicity):组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分。 

一致性(consistency):在事务处理执行前后,数据库是一致的(两个账户要么都变,或者都不变)。 

隔离性(isolcation):一个事务处理对另一个事务处理没有影响。 

持续性(durability):事务处理的效果能够被永久保存下来 。

1.1. 常用API

connection.setAutoCommit(false);

关闭自动提交, 打开事务。

connection.commit();

提交事务。 

connection.rollback();

回滚事务。

Savepoint sp = conn.setSavepoint();

设置保存点

conn.rollback(sp);

回滚到保存点

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

设置隔离级别, 可以通过Connection中的常量设置

1.2. 隔离级别

在多线程并发访问数据库并且使用事务的时候, 可能会遇到脏读, 不可重复读, 幻读的情况, 需要设置隔离级别来避免

脏读: 读到的线程未提交的数据

不可重复读: 在一个事务中读取同一个记录两次, 获取数据不同

幻读: 在一个事务中, 读取到的记录数不同

隔离级别

脏读

不可重复读

幻读

读未提交 Read Uncommitted

   √

读已提交 Read Committed

   √

   √

可重复读 Repeatable Read

   √

可序列化 Serializable

   

   

   

select @@tx_isolation;

查看隔离级别

set transaction isolation level read uncommitted;

设置读未提交

set transaction isolation level read committed;

设置读已提交

set transaction isolation level repeatable read;

设置可重复读

set transaction isolation level serializable;

设置可序列化

start transaction;

开始事务

rollback;

回滚事务

commit;

提交事务

获取插入的ID

conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

ResultSet rs = ps.getGeneratedKeys();

if (rs.next())

user.setId(rs.getInt(1));

MySQL的select last_insert_id()可以获取之前插入的记录的id, 但这只是MySQL才有的函数

只有对自增长的列发生自增长的赋值后才会导致一个key的产生,并且用getGereratedKeys()返回。

批处理

由于建立连接, 以及发送数据非常消耗性能, 如果有大批SQL命令需要处理, 最好使用批处理

ps = conn.prepareStatement("insert into user(name,password,email,birthday) values(?,?,?,?)");

for (User user : list) {

ps.setString(1, user.getName());

ps.setString(2, user.getPassword());

ps.setString(3, user.getEmail());

ps.setDate(4, new Date(user.getBirthday().getTime()));

ps.addBatch();

}

ps.executeBatch();

分页

通过ResultSet的滚动可以设置获取记录的位置, 但这样是从数据库中查询出所有数据, 然后再从结果中筛选结果, 性能非常低.

MySQL提供了分页语法. 在查询语句后可使用LIMIT关键字完成分页功能, 例如:

select * from user limit 40,20

查询从user表中取出从第41条开始的20条记录. 第一个参数表示忽略前面多少个, 第二个参数代表取多少个.

可更新结果集、敏感结果集

conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

ResultSet.TYPE_SCROLL_SENSITIVE

表示获得ResultSet之后是敏感的, 随数据库更新的. 但MySQL没有支持这项功能

ResultSet.CONCUR_UPDATABLE

表示获得ResultSet之后是可更新的, 例如:

rs.next();

rs.updateString("name", "updateName");

rs.updateRow();

可以将当前行的name属性改为updateName.

元信息

1.3. 数据库元信息

由于每种数据库对JDBC的实现都有所不同, 我们在使用的时候想要了解哪些数据库支持哪些功能, 就可以查看元信息

DatabaseMetaData data = conn.getMetaData();

数据库元信息

data.getDatabaseProductName()

数据库名

data.getDatabaseProductVersion()

数据库版本号

data.getDriverName()

驱动名

data.getDriverVersion()

驱动版本号

data.supportsTransactions()

是否支持事务

data.getDefaultTransactionIsolation()

默认事务隔离级别

data.supportsTransactionIsolationLevel(0)

是否支持指定的事务隔离级别

data.supportsGetGeneratedKeys()

是否支持获取主键

data.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE)

是否支持敏感结果集

1.4. 结果集元信息

我们可以根据结果集元信息来写一些灵活性很高的代码. 让代码的复用性更高.

ResultSetMetaData rsmd = ps.getMetaData();

获取结果集元信息

rsmd.getColumnCount()

获取结果集中包含几列

rsmd.getColumnName(1)

获取指定列的名字

rsmd.getColumnLabel(1)

获取指定列的别名

rsmd.getColumnClassName(1)

获取指定列的Java类型

rsmd.getColumnTypeName(1)

获取指定列的数据库类型

反射基础

1.5. 构造函数

Class.getConstructors()

获取所有构造函数

Class.getConstructor(Class...);

获取到class中带有指定类型参数的构造函数

Constructor.newInstance(Object...);

使用构造函数创建对象, 传入指定参数

1.6. 方法

Class.getMethods()

获取所有公有方法, 包括继承的

Class.getDeclaredMethods()

获取所有类中定义的方法, 包括私有的

Class.getMethod(String, Class...)

获取指定方法名和参数类型的方法(公有的)

Class.getDeclaredMethod(String, Class...)

获取指定方法名和参数类型的方法(类中定义的)

Method.invoke(Object, Object...)

在制定对象上运行方法, 将制定参数传入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值