package test;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import util.DBUtil;
public class TestDay02 {
/**
* 模拟转账的业务。
* 1.为了巩固今天的内容。
* 2.为了引出新知识点:事务。
*
* 假设用户(付款方)已经登录了网银,
* 要给别人(收款方)转账N元,
* 目前已经输入了收款方账号和金额。
*
* 转账的实现流程:
* 1)查询付款方余额,看够不够
* 2)查询收款方,判断账号对不对
* 3)修改付款方余额,减N元
* 4)修改收款方余额,加N元
*
*/
@Test
public void test6() {
//假设付款方输入了如下转账信息:
String payId = "00001";
String recId = "00002";
double mny = 1000.0;
//转账是一个完整的业务流程,
//整个过程应该在一个事务内,
//所以只能使用一个连接。
Connection conn = null;
try {
conn = DBUtil.getConnection();
//事实上JDBC默认会自动提交事务,
//在调用executeUpdate()时。
//要想保证当前业务在一个事务内,
//需要取消自动提交事务,改为手动提交。
conn.setAutoCommit(false);
//1.查询付款方余额
String sql =
"select * from accounts_lhh "
+ "where id=?";
PreparedStatement ps =
conn.prepareStatement(sql);
ps.setString(1, payId);
ResultSet rs = ps.executeQuery();
Double payMny = 0.0;
if(rs.next()) {
payMny = rs.getDouble("money");
if(payMny<mny) {
throw new SQLException("余额不足");
}
}
//2.查询收款方账号
String sql2 =
"select * from accounts_lhh "
+ "where id=?";
PreparedStatement ps2 =
conn.prepareStatement(sql2);
ps2.setString(1, recId);
ResultSet rs2 = ps2.executeQuery();
double recMny = 0.0;
if(!rs2.next()) {
throw new SQLException(
"收款账号错误");
} else {
recMny = rs2.getDouble("money");
}
//3.付款方-N
String sql3 =
"update accounts_lhh set "
+ "money=? where id=?";
PreparedStatement ps3 =
conn.prepareStatement(sql3);
ps3.setDouble(1, payMny-mny);
ps3.setString(2, payId);
ps3.executeUpdate();
Integer.valueOf("abc");
//4.收款方+N
String sql4 =
"update accounts_lhh set "
+ "money=? where id=?";
PreparedStatement ps4 =
conn.prepareStatement(sql4);
ps4.setDouble(1, recMny+mny);
ps4.setString(2, recId);
ps4.executeUpdate();
//代码正常执行结束后,提交一次事务
conn.commit();
} catch (Exception e) {
//发生异常时将数据回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
throw new RuntimeException(
"回滚失败", e1);
}
e.printStackTrace();
throw new RuntimeException(
"转账失败",e);
} finally {
DBUtil.close(conn);
}
}
/**
* 演示如何获取结果集元数据,
* 以及如何从该对象中获取相关信息。
*/
@Test
public void test5() {
//假设页面传入的查询条件如下
int deptno = 1;
Connection conn = null;
try {
conn = DBUtil.getConnection();
String sql =
"select * from emps_lhh "
+ "where deptno=?";
PreparedStatement ps =
conn.prepareStatement(sql);
ps.setInt(1, deptno);
ResultSet rs = ps.executeQuery();
//通过结果集获取其元数据,
//包含了对结果集的描述信息,
//即多少列、列名、列类型等。
ResultSetMetaData md = rs.getMetaData();
System.out.println(md.getColumnCount());
System.out.println(md.getColumnName(1));
System.out.println(md.getColumnType(1));
System.out.println(md.getColumnTypeName(1));
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(
"查询员工失败",e);
} finally {
DBUtil.close(conn);
}
}
/**
* 演示如何使用PS执行查询,
* 避免注入攻击。
*/
@Test
public void test4() {
//假设用户登录时输入的账号密码如下
String code = "zhangsan";
String pwd = "123' or 'a'='a";
Connection conn = null;
try {
conn = DBUtil.getConnection();
String sql =
"select * from users_lhh "
+ "where username=? "
+ "and password=?";
PreparedStatement ps =
conn.prepareStatement(sql);
ps.setString(1, code);
ps.setString(2, pwd);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(
"查询用户失败",e);
} finally {
DBUtil.close(conn);
}
}
/**
* 演示如何使用PS执行DQL语句
*/
@Test
public void test3() {
//假设页面传入的搜索条件如下
int empno = 1;
Connection conn = null;
try {
conn = DBUtil.getConnection();
String sql =
"select * from emps_lhh "
+ "where empno=?";
PreparedStatement ps =
conn.prepareStatement(sql);
ps.setInt(1, empno);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
System.out.println(
rs.getString("ename"));
System.out.println(
rs.getDouble("sal"));
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(
"查询员工失败",e);
} finally {
DBUtil.close(conn);
}
}
/**
* 演示如何使用PS执行DML语句
*/
@Test
public void test2() {
//假设页面传入的数据如下
String ename = "悟空";
String job = "保镖";
int mgr = 56;
Date hiredate =
Date.valueOf("2016-10-27");
double sal = 5000.0;
double comm = 0.0;
int deptno = 2;
Connection conn = null;
try {
conn = DBUtil.getConnection();
String sql =
"insert into emps_lhh values"
+ "(emps_seq_lhh.nextval,?,?,?,?,?,?,?)";
//创建ps,它会立刻发送SQL
PreparedStatement ps =
conn.prepareStatement(sql);
//设置参数值:
//ps.set类型(?的序号,?的值)
//注意保证个数和顺序
ps.setString(1, ename);
ps.setString(2, job);
ps.setInt(3, mgr);
ps.setDate(4, hiredate);
ps.setDouble(5, sal);
ps.setDouble(6, comm);
ps.setInt(7, deptno);
//让ps发送参数,并让DB执行SQL。
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(
"增加员工失败",e);
} finally {
DBUtil.close(conn);
}
}
/**
* 1.测试DBUtil
* 2.演示如何执行DQL
*/
@Test
public void test1() {
Connection conn = null;
try {
conn = DBUtil.getConnection();
System.out.println(conn);
Statement smt = conn.createStatement();
String sql =
"select * from emps_lhh "
+ "where empno<6";
//查询方法返回封装结果的对象ResultSet,
//它内部包含了多行数据,每行含有多列。
//该类是采用了迭代器模式设计的,
//所以通常采用while进行遍历。
ResultSet rs = smt.executeQuery(sql);
while(rs.next()) {
//每次遍历得到一行数据(含多列)
//1. rs.get类型(列索引)
//2. rs.get类型(列名)
System.out.println(rs.getInt("empno"));
System.out.println(rs.getString("ename"));
System.out.println("--------------");
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("创建连接失败",e);
} finally {
DBUtil.close(conn);
}
}
}