时间:2021-07-01 10:21:17 帮助过:11人阅读
JDBC:Java DataBase Connectivity,Java数据库连接。
(1)JDBC是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问。 它由一组由Java语言编写的类和接口组成。
(2)有了JDBC,程序员只需用JDBC API 写一个程序,就可以访问所有的数据库。
(3)将Java语言和JDBC结合起来,使程序员不必为不同的平台写不同的应用程序,只需写一遍程序就可以使它在任意平台上运行,这也是Java语言“一次编写,到处运行”的优势。
(4)简单地说,JDBC可以做三件事:与数据库建立连接,发送、处理数据库语句并处理结果。
加载Oracle的JDBC驱动程序。
见533题。
见533题。
execute、executeQuery,executeUpdate
(1)executeQuery:返回结果集(ResultSet),通常用于select语句。
(2)executeUpdate:返回此操作影响的行数(int),通常用于insert, update, delete语句。
(3)execute:返回布尔值(boolean),通常用于insert,update,delete语句。
while(rs.next()){//把游标从当前位置向下移动一行。
//rs.getString(1)中的参数“1”指的是数据表中的列号,也就是,数据表从//左到右,依次为第1列,第2列,第3列……;getString中的“String”是
//列号为1的列的数据类型对应到Java语言里是String类型的,所以用//getString来获取指定列的值,返回值也是String。
String ename = rs.getString(1);
// rs.getInt("empno")中的 “empno”指的是数据表中的列名(即字段)//getInt中的“Int”表示列名为“empno”的数据类型对应到Java语言里//是int类型的,所以用getInt来获取指定列的值,返回值也是int。
int empno = rs.getInt("empno");
}
1:加载一个Driver驱动。
2:创建数据库连接(Connection)。
3:创建SQL命令发送器Statement ;通过Statement发送SQL命令并得到结果。
4:处理结果(select语句和ResultSet);处理完毕后关闭数据库资源 。
大对象LOB(Large Object)是一种数据库数据类型,用来存储大数据量数据,如音频和图像等。
Oracle里有两种使用方法:
存储在数据库里,参与数据库的事务。有三种是这个大对象:BLOB, CLOB , NCLOB。
存储在数据库外的一种:BFILE ,不参与数据库的事务,也就是不能roolback 或者commit等,它依赖于文件系统的数据完整性。
(3)简单的代码示例:创建一个包含大对象数据类型的表;
CREATE TABLE waterfalls (
falls_name VARCHAR2(80),--name
falls_photo BLOB,--照片
falls_directions CLOB,--文字
falls_description NCLOB,--文字
falls_web_page BFILE);--指向外部的html页面
例如:使用JDBC完成用户的登录功能:
(1) SQL语句采用了字符串拼接String sql="select * from t_user where userno=‘"+userno+"‘ and password=‘"+upwd+"‘";
(2) 继而使用SQL命令发送器发送SQL命令并得到结果:stmt.executeQuery(sql);
(3) 如输入:userno=”abc”,password=”abc ‘or’1’=1”;
那上述sql字符串就变成:sql=”select * from t_user where userno=’abc’ and password=’abc ‘ or ’1’=’1’”;
这条语句中的用户名和密码并不正确,但仍然能访问数据表,所以存在风险。这就是SQL注入攻击。
(4) 解决方案:采用Statement的子接口PreparedStatement来实现, PreparedStatement的优点:
*1.可读性性强不繁琐。
*2.安全。
*3.多次执行同一条sql语句,效率高。
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
stmt=conn.createStatement();
String sql="select * from emp";
rs=stmt.executeQuery(sql);
int empNo=0;
String eName=null;
String job=null;
int mgr=0;
Date date=null;
String hireDate=null;
float salary=0;
float comm=0;
int deptNo=0;
while(rs.next()){
empNo=rs.getInt(1);
eName=rs.getString(2);
job=rs.getString(3);
mgr=rs.getInt(4);
date=rs.getDate(5);
hireDate=new SimpleDateFormat("YYYY/MM/DD").format(date);
salary=rs.getFloat(6);
comm=rs.getFloat(7);
deptNo=rs.getInt(8); System.out.println(empNo+"\t"+eName+"\t"+job+"\t\t"+mgr+"\t"+hireDate+"\t"+salary+"\t"+comm+"\t"+deptNo);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
stmt=conn.createStatement();
String sql="delete from emp where sal<1500";
System.out.println(stmt.executeUpdate(sql));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
PreparedStatement 接口继承 Statement接口
如果需要多次执行一个SQL语句,可以使用PreparedStatement对象。在创建PreparedStatement对象时,通过传递不同参数值多次执行PreparedStatement对象,可以得到多个不同的结果。
优势:执行效率高、代码可读性强、安全性高
(1)在JDBC中,事务操作缺省是自动提交。
a)一条对数据库的更新表达式代表一项事务操作
b)操作成功后,系统将自动调用commit()提交,否则调用rollback()回滚
(2)在JDBC中,事务操作方法都位于接口java.sql.Connection中
c)可以通过调用setAutoCommit(false)来禁止自动提交。
d)之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用 commit()来进行整体提交,
e)倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响 应的异常;
f)此时就可以在异常捕获时调用rollback()进行回滚,回复至数据初始状态
(3)事务结束的边界是commit或者rollback方法的调用
事务开始的边界则不是那么明显了,它会开始于组成当前事务的所有statement中的第一个被执行的时候。
以下是代码:
try {
stmt = conn.createStatement();
conn.setAutoCommit(false);
String sql1 ="update account set balance = balance-1000 where aid=1";
String sql2 ="update account set balance = balance+1000 where aid=2";
stmt.executeUpdate(sql1);
stmt.executeUpdate(sql2);
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
1.JDBC(Java DataBase Connectivity:Java数据库连接)有多种方式,其中一种是通过从资源文件读取加载方式来连接数据库。
2.JDBC最常用的资源文件类是Properties.
步骤是:
1)首先要创建一个文本文件,以.properties后缀名结尾,如db.properties.
2)以“键=值”的方式书写一个属性的配置信息,如:
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/student
db.username=root
db.password=root
3.代码示例:
(1)创建一个DbUtil.java类:
public class DbUtil{
//数据库驱动
privatestatic String Driver="";
//数据库地址
privatestatic String url="";
//数据库用户名
privatestatic String userName="";
//数据库密码
privatestatic String password="";
//创建static静态代码块,项目启动的时候就执行加载数据库连接的必要配置文件信息;
static {
Properties p=new Properties();
try {
//通过相对路径加载文件
p.load(new FileInputStream(new File("cof/Db.properties")));
//用getProperty方法通过关键字获取信息
Driver = p.getProperty("Driver");
url = p.getProperty("url");
userName = p.getProperty("userName");
password = p.getProperty("password");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//创建连接数据库的方法体;
public Connection getConn(){
Connection conn=null;
try {
//加载驱动
Class.forName(Driver);
//获取数据库连接
conn=DriverManager.getConnection(url,userName,password);
}
catch (SQLException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e){
e.printStackTrace();
}
return conn;
}
}
(2)测试:
publicclass TestDbutil {
publicstaticvoidmain(String[] args) {
//new一个DbUtil对象从而得到连接数据库的方法
DbUtil util = new DbUtil();
Connection conn = util.getConn();
//上面两条代码已经通过读取资源文件的方式建立了数据库连接,接下来就//可以按常规操作数据库了(此处略)
//操作完数据库关闭资源(略)
4.通过读取资源文件来创建数据库连接的好处:
以文件读取加载方式连接数据库,这种方式的好处在于当数据库驱动,地址或者用户名密码发生变动时,只需要在文件里改动即可,而不需要在代码里改动,这也很好体现了代码的封装性原则。
1.需要向数据库发送多条sql语句时, 为了提升执行效率, 可以采用JDBC的批处理机制。
2.JDBC的批处理机制主要有:Statement或PreparedStatement对象及以下方法:
(1)addBatch(String sql) :Statement类的方法, 多次调用该方法可以将多条sql语句添加到Statement对象的命令列表中。执行批处理时将一次性的把这些sql语句发送给数据库进行处理。
(2)addBatch(): PreparedStatement类的方法, 多次调用该方法可以将多条预编译的sql语句添加到PreparedStatement对象的命令列表中。执行批处理时将一次性的把这些sql语句发送给数据库进行处理。只能应用在类型相同参数不同的sql语句中, 此种形式的批处理经常用于在同一个表中批量插入数据, 或批量更新表的数据。
(3)executeBatch():把Statement对象或PreparedStatement对象命令列表中的所有sql语句发送给数据库进行处理。
(4)clearBatch(): 清空当前sql命令列表。
3.代码示例:
public class BatchTest {
public void statementBatch() {
Connection conn = null;
Statement st = null;
String sql_1 = "insert into student(name, age) values(‘李明‘, 24)";
String sql_2 = "insert into student (name, age) values(‘李然‘, 22)";
String sql_3 = "insert into student (name, age) values(‘王雷‘, 21)";
String sql_4 = "update student set name=‘张衡‘ where id=1";
try {
conn = JdbcUtils.getConnection();
st = conn.createStatement();
st.addBatch(sql_1);
st.addBatch(sql_2);
st.addBatch(sql_3);
st.addBatch(sql_4);
st.executeBatch();
st.clearBatch();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(null, st, conn);
}
}
public void preparedStatementBatch() {
Connection conn = null;
PreparedStatement st = null;
String sql = "insert into student (name, age) values(?, ?)";
try {
conn = JdbcUtils.getConnection();
//通过只打开一个连接 ;
st = conn.prepareStatement(sql);
for (int i = 0; i < 10; i++) {
st.setString(1, "SN_" +( i+1));
st.setInt(2, i+10);
st.addBatch();
// 需要防止Preparedstatement对象中的命令列表包含过多的待处理sql语句, 而造成outOfMemory错误
if (i % 5== 0) {
st.executeBatch();
st.clearBatch();
}
}
// 将剩下的未处理命令发送给数据库 ;
st.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(null, st, conn);
}
}
}
4.JDBC批处理的好处:
前期的代码在与数据库进行通信时,都是先建立连接,建立连接花费的成本是最高的,然后发一个SQL语句,执行完后就关闭了连接。还有一个问题是发送的SQL语句都是通过网络传送的,比起本地调用来说,网络传输的成本也是高很多的。如果要插入或者更新一批数据进数据库,还是采用前期的方法,花费的时间会很多,给用户的感受会很慢。但是如果采用批处理,则在两个方便都会节约大部分成本,速度会更快。
注意:不要一次性向命令列表中添加数量过多的sql语句, 防止出现outOfMemory错误。
JDBC技术
标签:commit update 应用 trace 方法 速度 字符 lex 流程