#JDBC
Java Database Connectivity:Java访问数据库的解决方案。
SUN公司编写了JDBC定义了一套标准接口,即访问数据库的通用API,不同的数据库厂商根据各自数据库的特点去实现这些接口。
#properties也是一种配置文件
- 如db.properties的文件内容如下:
#database connection parameters
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:orcl
user=lhh
pwd=1234
- 读取它的方法
Properties p = new Properties();
p.load(DBTool.class.getClassLoader().getResourceAsStream("db.properties"))
String driver = p.getProperty("driver");
url = p.getProperty("url");
user = p.getProperty("user");
pwd = p.getProperty("pwd");
#JDBC的工作流程
##获取连接的两种方法
###DriverManager
Class.forName("oracle.jdbc.OracleDriver")
//根据url连接参数,找到与之匹配的Driver对象,调用其方法获取连接
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.0.26:1521:orcl",
"用户名","密码");
- 直接使用DriverManager的问题
- 它没有管理连接上限,并发量大时很容易导致数据库崩溃每次调用它,它都创建新连接,而不是复用连接,效率低
###连接池/数据源 - BasicDataSourcedataSource
private static BasicDataSource dataSource = new BasicDataSource();
//加载参数
dataSource.setDriverClassName(driveClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
String initSize = p.getProperty("init_size");
String maxSize = p.getProperty("max_size");
//获得连接
Connection conn = dataSource.getConnection();
-
连接池可以解决的问题
它能管理连接上限,避免数据库崩溃
它可以让我们复用连接,提高效率 -
有哪些常用连接池?
DBCP
C3P0
##两种不同的语句对象Statement和PreparedStatement
###Statement
Statement适合执行静态(无条件)SQL
- 图解:
- 使用
Statement smt = conn.createStatement();
String sql = “insert into emps values(”
+ “emps_seq.nextval,‘唐僧’,‘总监’,0”
+ “,sysdate,8000.0,6000.0,2)”;
//返回sql所能影响(增删改)的行数
//该方法在执行完sql后会自动commit
int rows = smt.executeUpdate(sql);
System.out.println(rows);
###PreparedStatement
PreparedStatement适合执行动态(有条件)SQL会进行预编译。
-
图解
-
使用:
conn = DBUtil.getConnection();
//创建ps对象,并让它立刻发送SQL
String sql = "select * from emps where empno=?";
PreparedStatement ps = conn.prepareStatement(sql);
//给?赋值
//ps.set类型(?的序号,?的值)
ps.setInt(1, empno);
//发送条件,执行SQL
ResultSet rs = ps.executeQuery();
while(rs.next()) {
System.out.println(rs.getString("ename"));
System.out.println(rs.getDouble("sal"));
}
##ResultSet
- 结果集的指针
###结果集元数据ResultSetMetaData
结果集元数据:对结果集进行描述(概括)的数据
包含:多少列,列名,列的类型
conn = DBUtil.getConnection();
String sql = "select * from emps order by empno";
Statement smt = conn.createStatement();
ResultSet rs = smt.executeQuery(sql);
//获取结果集元数据
ResultSetMetaData md = rs.getMetaData();
System.out.println(md.getColumnCount());
System.out.println(md.getColumnName(1));
System.out.println(md.getColumnTypeName(1));
#JDBC中的事务管理
- 自动管理事务
- JDBC会自动管理事务
- 每次调用executeUpdate()时,它会自动commit
- 一个业务只需执行一次DML时,采用自动管理事务
- 手动管理事务
- 取消自动提交:conn.setAutoCommit(false)
- 采用手动提交:conn.commit()
- 异常时要回滚:conn.rollback()
一个业务需要执行多次DML时,采用手动管理事务
- 什么是事务?
- 满足如下规则的数据库访问叫事务
原子性:事务是一个完整的过程,要么都成功,要么都失败.
一致性:事务前后的数据要保持一致,即收支平衡.
隔离性:事务访问过程中的数据,不能被别人访问.
持久性:事务一旦完成,就永久生效.
要整体的看待事务的概念,不要割裂来理解.
#批量添加
- 使用场景
在企业软件上线时,导入原始数据,则需要进行批量添加. - 如何实现
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
String sql = "insert into emps values("
+ "emps_seq.nextval,?,?,?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
for(int i=1;i<=108;i++) {
ps.setString(1, "好汉"+i);
ps.setString(2, "打劫");
//省略5行
//将此数据暂存到ps对象上
ps.addBatch();
if(i%50==0) {
//将ps上暂存的50条数据发送给数据库
ps.executeBatch();
//将ps上暂存的数据清空,以便下一轮发送
ps.clearBatch();
}
}
//为避免有零头数据,再单独发送一次
ps.executeBatch();
conn.commit();
#获取自动生成的主键
-
使用场景
在增加主外键对应的2张表的数据时,需要获得主表自动生成的主键.
-
使用:
//给新增加的部门添加一个员工
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
//增加部门
String sql = "insert into depts values("+ "depts_seq.nextval,?,?)";
//参数2是一个字符串数组,内含主键字段名,
//即告诉ps希望它返回哪个主键字段的值.
PreparedStatement ps = conn.prepareStatement(sql, new String[]{"deptno"});
ps.setString(1, dname);
ps.setString(2, loc);
ps.executeUpdate();
//从ps中获得生成的主键的值
ResultSet rs = ps.getGeneratedKeys();
rs.next();
//获取主键值时不能通过字段名获取
int deptno = rs.getInt(1);
//增加员工
sql = "insert into emps values("+ "emps_seq.nextval,?,?,?,?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, ename);
//省略
conn.commit();
#DAO
#JDBC支持如下的日期类型
- java.sql.Date 年月日
- java.sql.Time 时分秒
- java.sql.Timestamp 完整日期
上述日期都是java.util.Date的子类
#JavaBean? - 满足如下规范的类
- 该类必须有包
- 该类必须有无参构造器
- 该类必须实现序列化接口
- 该类通常有get和set方法