在java中可以通过直接向数据库传输SQL语言字符串的方式来调用数据库中的数据,但这样会有很多缺点,比如说容易被他人从网络注入SQL语句,传输数据量大影响效率之类的。
所以一般的JAVA程序操作数据库的方式都是通过事先在数据库中用PL/SQL编程建立好我们需要操作的过程或者函数,然后由JAVA程序通过JDBC直接来调用数据库中的过程来达到我们的目的,这样他人就难以从网络悄悄的注入SQL语句来窃取我们数据库的数据了,并且传输的数据量也变小的,优化了效率。
下面是用JDBC调用数据库中的过程和函数来达到获取和修改数据的目的的一个实例:
1.首先我们用scott用户登录,给它新建一个LOL表,再给表中插入一些数据
--新建一个表
create table lol(heronum number(5),heroname varchar2(10),herotype varchar2(10));
(建立一个序列,来给表中的每一条数据一个连续的编号)
--新建一个序列()
create or replace sequence seq_lol
start with 1 --从0开始
increment by 1 --每次增加1
maxvalue 100 --最大值为100
nocycle --不循环
nocache --没有缓存(语句执行失败时不会增加)
--给表中插入数据
insert into lol values(seq_lol.nextval,'盖伦','肉盾');
insert into lol values(seq_lol.nextval,'赵信','近战');
insert into lol values(seq_lol.nextval,'易','近战');
insert into lol values(seq_lol.nextval,'提莫','射手');
insert into lol values(seq_lol.nextval,'瑞兹','法师');
2.(修改数据)我们发现表中插入的第一条数据错了,盖伦应该是近战类型的,这里定义一个过程来通过输入一个heroname来修改这条数据的herotype.
--通过输入一个英雄的名字,来修改他的类型
create or replace procedure pro_updateTypeByName(v_heroname varchar2,v_herotype varchar2) is
begin
update lol set herotype=v_herotype where heroname=v_heroname;
end;
3.通过JDBC来调用数据库中的过程,修改名字为盖伦的英雄的类型.
(1)首先在JAVA中写一个类用来获得连接数据库的连接对象(此处将这个类的构造方法私有化了,这样让外界只能通过调用它里面的静态方法来获得对象,然后再在这个取得对象的静态方法里作一系列判断,让程序的运行中只存在一个连接对象,这样就节约了程序的资源,优化了数据库与JAVA的连接效率).
/**
* 连接数据库,获得数据库连接对象
* @author yy
*
*/
public class DBUtil {
private static Connection conn;
//将构造方法私有化,让这个类只能通过调用下面的静态方法来创建对象
private DBUtil(){
}
public static Connection getconn(){
if(conn==null){
try {
//装载驱动(此处先要在工程处引入外界的JDBC包)
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@172.19.238.127:1521:ORCL";
//获得数据库连接
conn = DriverManager.getConnection(url, "scott", "scott");
return conn;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
return conn;
}
}
(2).定义一个操作类,类中创建一个用来执行数据库中过程的方法.
public class EXEChw {
/**
* 通过名字修改类型
* @param name 要修改英雄的名字
* @param newtype 要修改成的类型
*/
public void setTypeByName(String name,String newtype){
try{
//获得数据库连接对象
Connection conn = DBUtil.getconn();
//定义调用过程的SQL语句(此处的?是一个占位符,在编译了SQL语句之后再给它赋值,这样可以防止全能等式的BUG)
String sql = "{call pro_updateTypeByName(?,?)}";
//获得编译对象
CallableStatement cstm = conn.prepareCall(sql);
//给?赋值
cstm.setString(1, name);
cstm.setString(2, newtype);
//执行过程
cstm.execute();
}catch(Exception e){
e.printStackTrace();
}
}
}
(3).通过调用方法来执行数据库中的过程,修改数据库中的内容,将盖伦的类型改为近战
EXEChw eh = new EXEChw();
eh.setTypeByName("盖伦", "近战");
(4).在数据库中查看lol表,看以上操作是否改变了盖伦的类型
SQL> select * from lol;
HERONUM HERONAME HEROTYPE
------- ---------- ----------
1 盖伦 近战
2 赵信 近战
3 易 近战
4 提莫 射手
5 瑞兹 法师
SQL>
3.(取得数据)我们要通过输入一个英雄的编号,取得这个英雄的所有信息
(1).在数据库中创建这个过程.
--通过输入一个英雄的编号,来获得这个英雄的所有信息
create or replace procedure pro_getAllByNum(v_heronum in number,v_heroname out varchar2,v_herotype out varchar2) is
begin
select heroname,herotype into v_heroname,v_herotype from lol where heronum=v_heronum;
end;
(2).在EXChw类中创建一个方法来通过JDBC调用这个过程,获得该编号英雄的名字和类型输出.
/**
* 通过编号来获得名字和类型
* @param num 依据的编号
*/
public void getNameTypeByNum(int num){
try{
//获得数据库连接对象
Connection conn = DBUtil.getconn();
//定义调用过程的SQL语句(此处的?是一个占位符,在编译了SQL语句之后再给它赋值,这样可以防止全能等式的BUG)
String sql = "{call pro_getAllByNum(?,?,?)}";
//获得编译对象
CallableStatement cstm = conn.prepareCall(sql);
//给第一个?赋值
cstm.setInt(1, num);
//给第二三个?注册输出的参数
cstm.registerOutParameter(2, java.sql.Types.VARCHAR);
cstm.registerOutParameter(3, java.sql.Types.VARCHAR);
//执行过程
cstm.execute();
//获得输出的参数的值
String name = cstm.getString(2);
String type = cstm.getString(3);
//输出
System.out.println("名字:"+name+",类型:"+type);
}catch(Exception e){
e.printStackTrace();
}
}
(3).JAVA中的输出为
名字:易,类型:近战
4.显示lol表中的所有数据(游标的使用)
太晚了,明天写 ≡ ‘(*>﹏<*)′ ~