Unit02: JDBC核心API
Unit02: JDBC核心API
db.properties
注意:如果使用连接池,可以在这个文件中增加对连接池的相关设置:
连接池参数,常用参数有:
- 初始连接数
- 最大连接数
- 最小连接数
- 每次增加的连接数
- 超时时间
- 最大空闲连接
- 最小空闲连接
# db connection parameters
# key=value
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@192.168.201.227:1521:orcl
user=openlab
pwd=open123
# datasource parameters
initSize=1
maxSize=1
DBUtil.java
说明:DBUtil是DBTool的升级版,采用了连接池来管理连接。
package util; import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; import org.apache.commons.dbcp.BasicDataSource; /**
* 1.DBUtil是DBTool的升级版
* 2.采用了连接池来管理连接
*/
public class DBUtil { //DBCP连接池提供的实现类
private static BasicDataSource ds; static {
Properties p = new Properties();
try {
//1.读取参数
p.load(DBUtil.class.getClassLoader()
.getResourceAsStream("db.properties"));
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String user = p.getProperty("user");
String pwd = p.getProperty("pwd");
String initSize = p.getProperty("initSize");
String maxSize = p.getProperty("maxSize");
//2.创建连接池(1次)
ds = new BasicDataSource();
//3.向连接池设置参数
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(pwd);
ds.setInitialSize(new Integer(initSize));
ds.setMaxActive(new Integer(maxSize));
} catch (IOException e) {
//异常的处理原则:
//1.记录日志(Log4j)
e.printStackTrace();
//2.能解决就解决(看开发规范)
//3.解决不了向上抛给调用者
//具体抛出哪种类型的异常看开发规范
throw new RuntimeException(
"加载配置文件失败", e);
}
} public static Connection getConnection()
throws SQLException {
return ds.getConnection();
} /**
* 1.目前我们使用连接都是连接池创建的
* 2.连接池重写了连接对象内部的close()
* 3.目前close()内部的逻辑是归还:
* - 清除连接对象内部包含的所有数据
* - 将连接对象状态设置为空闲态
*/
public static void close(Connection conn) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(
"关闭连接失败", e);
}
}
} }
Test.java
说明:这个类用于测试DBUtil
package jdbc; import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import org.junit.Test; import util.DBUtil; public class TestDay02 { /**
* 1.测试DBUtil
* 2.执行DQL
* 查询部门ID为1的员工
*/
@Test
public void test1() {
//假设页面传入的查询条件是
int deptno = 1; Connection conn = null;
try {
conn = DBUtil.getConnection();
System.out.println(conn);
Statement smt = conn.createStatement();
String sql =
"select * from emps_lhh "
+ "where deptno="+deptno;
ResultSet rs = smt.executeQuery(sql);
while(rs.next()) {
System.out.println(rs.getInt("empno"));
System.out.println(rs.getString("ename"));
}
} catch (SQLException e) {
e.printStackTrace();
//测试代码可以适当简化异常处理
} finally {
DBUtil.close(conn);
}
} /**
* 演示如何使用PS执行DML
*/
@Test
public void test2() {
//假设页面传入的数据是
String ename = "曹操";
String job = "丞相";
int mgr = 0;
Date hiredate =
Date.valueOf("2017-01-22");
Double sal = 8000.0;
Double comm = 9000.0;
int deptno = 3; Connection conn = null;
try {
conn = DBUtil.getConnection();
//写sql时条件用?代替
String sql =
"insert into emps_lhh values("
+ "emps_seq_lhh.nextval,"
+ "?,?,?,?,?,?,?)";
//创建PS并传入sql,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);
//发送参数,执行SQL(计划)
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} 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.getString("job"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn);
} } /**
* 使用PS执行查询语句,可以避免注入攻击
*/
@Test
public void test4() {
//假设页面传入的参数是
String user = "zhangsan";
String pwd = "a' or 'b'='b"; 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, user);
ps.setString(2, pwd);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("账号或密码错误");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn);
}
} }
Test.java
- 演示如何从ResultSetMetaData中读取结果集相关的描述信息.
- 模拟转账业务.
- 批量添加员工(共108个,每批加50个)
- 添加部门及员工数据,添加员工时需要获取到部门的ID
package jdbc; 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 org.junit.Test; import util.DBUtil; public class TestDay03 { /**
* 演示如何从ResultSetMetaData
* 中读取结果集相关的描述信息.
*/
@Test
public void test1() {
//假设页面传入的查询条件是
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();
//获取结果集元数据,它是一个对象,
//内部封装了对结果集的描述信息.
ResultSetMetaData md = rs.getMetaData();
//多少列
System.out.println(md.getColumnCount());
//第1列的列名
System.out.println(md.getColumnName(1));
//第1列的类型的编号(常量)
System.out.println(md.getColumnType(1));
//第1列的类型的名称
System.out.println(md.getColumnTypeName(1));
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn);
}
} /**
* 模拟转账业务.
*
* 假设此时用户已经登录了网银,
* 并且已经输入了收款方账号和
* 转账的金额,点击了转账.
*
* 转账的步骤:
* 1.验证收款方账号是否存在(查询)
* 2.验证付款方余额是否够用(查询)
* 3.将付款方余额-N元(修改)
* 4.将收款方余额+N元(修改)
*/
@Test
public void test2() {
//假设用户输入的信息如下
//付款方账号
String payId = "00001";
//收款方账号
String recId = "00002";
//转账的金额
double mny = 1000.0; //转账是一个完整的业务流程,必须保证
//它的完整性,即该流程应处于一个事务
//之内,所以创建一个连接.
Connection conn = null;
try {
conn = DBUtil.getConnection();
//取消自动提交事务
conn.setAutoCommit(false);
//1.查询收款方账号并验证
String sql =
"select * from accounts_lhh "
+ "where id=?";
PreparedStatement ps =
conn.prepareStatement(sql);
ps.setString(1, recId);
ResultSet rs = ps.executeQuery();
if(!rs.next()) {
throw new SQLException("收款方账号不存在");
}
double recMny = rs.getDouble("money");
//2.查询付款方余额并验证
String sql2 =
"select * from accounts_lhh "
+ "where id=?";
PreparedStatement ps2 =
conn.prepareStatement(sql2);
ps2.setString(1, payId);
ResultSet rs2 = ps2.executeQuery();
double payMny = 0.0;
if(rs2.next()) {
payMny = rs2.getDouble("money");
if(payMny<mny) {
throw new SQLException("余额不足");
}
}
//3.修改付款方余额
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("断电了"); //4.修改收款方余额
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) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
DBUtil.close(conn);
}
} /**
* 批量添加员工(共108个,每批加50个)
*/
@Test
public void test3() {
//这是一个完整的业务,只创建
//1个连接,提交1次事务
Connection conn = null;
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
String sql =
"insert into emps_lhh values("
+ "emps_seq_lhh.nextval,"
+ "?,?,?,?,?,?,?)";
PreparedStatement ps =
conn.prepareStatement(sql);
for(int i=1;i<=108;i++) {
//每次循环都将数据暂存到ps上
ps.setString(1, "好汉"+i);
ps.setString(2, "打劫");
ps.setInt(3, 0);
ps.setDate(4,
Date.valueOf("2017-01-23"));
ps.setDouble(5, 6000.0);
ps.setDouble(6, 4000.0);
ps.setInt(7, 9);
ps.addBatch();
//每循环50次发送一次数据
if(i%50==0) {
ps.executeBatch();
//清空ps中的数据,以便于
//暂存下一轮的数据
ps.clearBatch();
}
}
//循环结束后,为了避免有零头(8),
//再单独批量发送一次数据.由于这
//是最后一次发送,所以不用清空ps了
ps.executeBatch();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
DBUtil.close(conn);
}
} /**
* 添加部门及员工数据
* 添加员工时需要获取到部门的ID
*/
@Test
public void test4() {
//假设页面传入的数据是
//部门
String dname = "财务部";
String loc = "杭州";
//员工
String ename = "郭嘉";
String job = "谋士";
int mgr = 0;
Date hiredate =
Date.valueOf("2017-01-23");
double sal = 6000.0;
double comm = 2000.0; Connection conn = null;
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
//增加部门
String sql =
"insert into depts values("
+ "depts_seq.nextval,?,?)";
//参数2是一个数组,声明需要ps记住
//的字段的名称,ps在执行SQL时会
//记住这些字段的值.
PreparedStatement ps =
conn.prepareStatement(
sql, new String[]{"deptno"});
ps.setString(1, dname);
ps.setString(2, loc);
ps.executeUpdate();
//获取部门ID
//返回的结果集中存储了一条数据,
//该行数据包括我们让ps记录的所有字段.
ResultSet rs = ps.getGeneratedKeys();
System.out.println("rs"+rs);
//rsorg.apache.commons.dbcp.DelegatingResultSet@27efef64
rs.next();
//获取ps记录的字段时必须使用序号
int deptno = rs.getInt(1);
System.out.println("deptno"+deptno); //deptno 4
//增加员工
String sql2 =
"insert into emps values("
+ "emps_seq.nextval,"
+ "?,?,?,?,?,?,?)";
PreparedStatement ps2 =
conn.prepareStatement(sql2);
ps2.setString(1, ename);
ps2.setString(2, job);
ps2.setInt(3, mgr);
ps2.setDate(4, hiredate);
ps2.setDouble(5, sal);
ps2.setDouble(6, comm);
ps2.setInt(7, deptno);
ps2.executeUpdate();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
DBUtil.close(conn);
}
} }
Unit02: JDBC核心API的更多相关文章
- JDBC核心API
JDBC核心API在java.sql.*和javax.sql.* 1.Driver接口:表示Java驱动程序接口,具体的数据库厂商要实现其此接口 connect(url.propertis):连接数据 ...
- JavaEE JDBC 核心API
JDBC接口核心的API @author ixenos java.sql.* 和 javax.sql.* |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口 ...
- hibernate系列笔记(2)---Hibernate的核心API
Hibernate的核心API 一般我们通过hibernate进行操作的时候,都会遵循下面的流程,那么接下来我对每一个步骤进行讲解: 1 public void testInsert() { 2 // ...
- hibernate框架(2)---Hibernate的核心API
Hibernate的核心API 一般我们通过hibernate进行操作的时候,都会遵循下面的流程,那么接下来我对每一个步骤进行讲解: 1 public void testInsert() { 2 // ...
- hibernate框架学习第二天:核心API、工具类、事务、查询、方言、主键生成策略等
核心API Configuration 描述的是一个封装所有配置信息的对象 1.加载hibernate.properties(非主流,早期) Configuration conf = new Conf ...
- Hibernate_day01--Hibernate配置文件详解_核心api
Hibernate映射配置文件(重点) 1 映射配置文件名称和位置没有固定要求 2 映射配置文件中,标签name属性值写实体类相关内容 (1)class标签name属性值实体类全路径 (2)id标签和 ...
- 配置文件详解和核心api讲解
一.配置文件详解 1.映射文件详解 1.映射配置文件的位置和名称没有限制. -建议:位置:和实体类放在统一目录下. 名称:实体类名称.hbm.xml. 2.在映射配置文件中,标签内的name属 ...
- Activiti6系列(5)- 核心API
前言 本来想把<疯狂工作流讲义-activiti6.0>这本书里面的实例拿过来,但是这本书我看完后,认为里面编写的activiti6的核心API代码片段不是很清晰,有不少需要雕琢的地方才好 ...
- 三大框架 之 Hibernate框架概述(概述、配置、核心API)
目录 Hibernate框架概述 什么是框架 hibernate简介(JavaEE技术三层架构所用到的技术) hibernate是什么框架 ORM hibernate好处 Hibernate基本使用 ...
随机推荐
- ansible入门五
一.Ansible条件测试 在ansible中还可以进行条件测试.如果需要根据变量.facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试. 1. when语句 在task后添加 ...
- 使用群晖NAS:配置Git server
1.首先在群晖的DSM的控制面板中创建一个用户例如是Git_test(我给了管理员权限) 2.在套件中心安装 Git server 3.打开Git server 勾选用户 Git_test 4.在控制 ...
- C++高级编程2. 静态动态链接库
C++高级编程2. 静态动态链接库20131018 1.动态链接库和静态链接库的区别: 静态链接库就是把lib文件中用到的函数代码直接连接进目标程序,程序运行的时候不在需要其他的库文件:动态链接库是把 ...
- operator[],识别读操作和写操作
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- LeetCode OJ:Number of 1 Bits(比特1的位数)
Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also know ...
- 关于Spinlock机制的一点思考
存在两段代码同时在多核上执行的情况,这时候才需要一个真正的锁来宣告代码对资源的占有. 几个核可能会同时access临界区,这时的spinlock是如何实现的呢? 要用到CPU提供的一些特殊指令,对lo ...
- 解决错误:This bundle is invalid - The file extension must be .zip
近期在 iOS 开发中遇到了一个很蛋疼的问题,Xcode 工程中接入了iMessage 壁纸的功能后,每次上传 ipa 包都会显示此包无效,并报上述的错误描述:This bundle is inval ...
- 2018秋C语言程序设计(初级)作业- 第3次作业
7-1 找出最小值 #include<stdio.h> int main() { int min,i,n,count; scanf("%d",&n); for( ...
- Spring之基础
Spring之目的 Spring致力于简化企业级Java开发,促进代码的松散耦合.成功的关键在于依赖注入(DI)和面向切面编程(AOP) Spring之DI DI是组装应用对象的一种方 ...
- 【剑指offer】左旋转字符串,C+实现
原创博文,转载请注明出处! 本题牛客网地址 本题代码的github地址 本系列文章的索引地址 # 题目 # 思路 先局部翻转,后整体翻转.举例:abcdefg先局部翻转为bagfedc,后整体翻转为c ...