数据库Mysql拔高: 存储过程、事务、
一、获取数据库自动生成的主键
主键的值最好由自己的程序来维护
注: 只对insert有效
例:
-------------------------------------------------------------------------------
create database day16;
use day16;
create table t1(
id int primary key auto_increment,
name varchar(100)
);
-------------------------------------------------------------------------------
// 获取数据库自动生成的主键
public class GetDBGenKeyDemo {
@Test
public void test(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
conn = JdbcUtil.getConnection();
// 获取数据库插入的主键的值 : 第二个参数默认可以省略: 注: 此参数仅对insert操作有效
// stmt = conn.prepareStatement("insert into t1 (name) values(?)", Statement.RETURN_GENERATED_KEYS);
stmt = conn.prepareStatement("insert into t1 (name) values(?)");
stmt.setString(1, "gfy");
stmt.executeUpdate();
// 以下就是获取数据库生成的主键的值
rs = stmt.getGeneratedKeys(); // 一行一列
if(rs.next()){
System.out.println(rs.getInt(1));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.release(rs, stmt, conn);
}
}
-------------------------------------------------------------------------------
二、存储过程(详解参考后面的oracle)
delimiter $$ 重新定义分界符
例:
******************************************************************
创建存储过程: 用字符串welcome---与传入的参数进行连接后返回
delimiter $$ // 修改分界符为$$
CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam varchar(255))
BEGIN
SELECT CONCAT('welcome---', inputParam) into inOutParam;
END $$
delimiter ;
// 还原分界符为;
******************************************************************
调用存储过程
public class InvokeProcedureDemo {
@Test
public void test(){
Connection conn = null;
CallableStatement stmt = null; // 调用存储过程的类
ResultSet rs = null;
try{
conn = JdbcUtil.getConnection();
// 书写格式
stmt = (CallableStatement) conn.prepareCall("{call demoSp(?,?)}");
// 存储过程的输入参数,给值即可; 输出参数: 要告诉它参数的类型
stmt.setString(1, "to shanghai");
stmt.registerOutParameter(2, Types.VARCHAR);
// 调用存储过程
stmt.execute();
// 得到存储过程中的值并输出
String value = stmt.getString(2);
System.out.println(value);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.release(rs, stmt, conn);
}
}
}
******************************************************************
三、事务入门
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功
TPL:事务控制语句
start transaction:开启一次事务
rollback: 回滚
commit:提交事务
JDBC中与事务有关的方法:
Connection.setAutoCommit(boolean b)
Connection.rollback()
Connection.rollback(Savepoint sp)
Connection.commit();
例:
***************************************************************************
use day16;
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
***************************************************************************
public class TransactionDemo {
@Test // aaa给bbb转账100
public void test1(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
conn = JdbcUtil.getConnection();
//事务是默认开启的
// 手工开启事务
conn.setAutoCommit(false);
// 事务的开始: 相当于: start transaction
// 在同一事务中的语句
stmt = conn.prepareStatement("update account set money=money-100 where name='aaa'");
stmt.executeUpdate();
//
int i = 1/0;
stmt = conn.prepareStatement("update account set money=money+100 where name='bbb'");
stmt.executeUpdate();
conn.commit(); // 提交事务: commit
}catch(Exception e){
e.printStackTrace();
try{
conn.rollback(); // 事务的回滚
}catch (SQLException e1){
e1.printStackTrace();
}
}finally{
JdbcUtil.release(rs, stmt, conn);
}
}
@Test // aaa转给bbb 100, bbb转给ccc 100
public void test2(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
Savepoint sp = null;
try{
conn = JdbcUtil.getConnection();
conn.setAutoCommit(false);
stmt = conn.prepareStatement("update account set money=money-100 where name='aaa'");
stmt.executeUpdate();
stmt = conn.prepareStatement("update account set money=money+100 where name='bbb'");
stmt.executeUpdate();
sp = conn.setSavepoint();
// 设置回滚点
stmt = conn.prepareStatement("update account set money=money-100 where name='bbb'");
stmt.executeUpdate();
//
int i = 1/0;
// bbb给ccc转账的时候出现异常 此时要回滚
stmt = conn.prepareStatement("update account set money=money+100 where name='ccc'");
stmt.executeUpdate();
}catch(Exception e){
e.printStackTrace();
try {
conn.rollback(sp); // 回滚到设置的回滚点sp
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
JdbcUtil.release(rs, stmt, conn);
}
}
}
***************************************************************************
四、事务的特性(隔离级别)
A:原子性。说明事务是一个不可分割的单位。
C:一致性.事务必须使数据库从一个一致性状态变换到另外一个一致性状态.(比如转账)
*I:隔离性。一个事务不能被其他事务打扰。
D:持久性。事务一旦提交,就应该被永久保存起来。
如果不考虑事务的隔离级别,会出现以下“不正确”的情况:
脏读:指一个事务读到了另一个事务中未提交的数据。
不可重复读:针对一条记录的,同一条记录前后不一样
虚读(幻读):针对一张表,前后读到的记录条数不一样。
MySQL中控制事务隔离级别的语句:
select @@tx_isolation; //查看当前的事务隔离级别
set transaction isolation level 你的级别(四种之一);//设置隔离级别
隔离级别的分类:
READ UNCOMMITTED:脏读、不可重复读、虚读都有可能发生。
READ COMMITTED:能避免脏读,不可重复读、虚读都有可能发生。
REPEATABLE READ:能避免脏读、不可重复度,虚读都有可能发生。
SERIALIZABLE:能避免脏读、不可重复度、虚读。
注: 事务的隔离级别必须用在事务之中;
一定要在事务开启之前设置事务的隔离级别,否则无效
例:
**********************************************************************************
脏读的演示:
public class TransactionIsolationDemo {
@Test
public void test(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
conn = JdbcUtil.getConnection();
// 设置事务的隔离级别 注: 一定要在事务开启之前设置事务的隔离级别,否则无效
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
conn.setAutoCommit(false);
stmt = conn.prepareStatement("select * from account where name='aaa'");
rs = stmt.executeQuery();
if(rs.next()){
System.out.println("开始时的余额:"+rs.getString("money"));
}
Thread.sleep(20*1000); // 此时开启另一个dos,模拟多线程操作
stmt = conn.prepareStatement("select * from account where name='aaa'");
rs = stmt.executeQuery();
if(rs.next()){
System.out.println("别人未提交事务时的余额:"+rs.getString("money"));
}
}catch(Exception e){
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
JdbcUtil.release(rs, stmt, conn);
}
}
}
**********************************************************************************
mysql 存储过程与事务案例 mysql存储过程中使用事务
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
mysql 存储过程返回更新前记录
mysql 存储过程返回更新前记录
存储过程 字段 自连接