之前闲来无事在研究存储过程 觉得jdbc调用存储过程效率太低就想有没有更高效的方式?最好能用面对对象思想一个方法调用, 传入过程名称就好?于是打开了百度搜索一番 还真找到了一篇很赞的文章,英雄所见略同啊,想到一块去了 博主已经封装的很好了 叫JAVA调用存储过程的另类封装的开发日志(一)http://nikoloss.iteye.com/blog/1734487 然后没有了 what? 有一那肯定还有二啊,说明一是不全的 那么我理所当然的去搜索二 纳尼? 没有 次奥 说明这个博主很懒!最起码比我懒,好了开玩笑的,不过这个博主已经写的很好很好了 但还是无法真正投入使用 干脆我就用博主的思路继续重新写一篇完整的好了,这次的目的是继续封装生成一个jar包 以后导入就可以用了 这个包后面我会上传的 建议先看上面那个博客后再来看 因为思想一样很多话就没必要在重复讲解了
这里就用orcle中的emp和dept表也就是员工和部门表
首先是emp实体对象
package test.bean;
import java.util.Date;
public class Emp {
private int empno;
private String ename;
private String job;
private int mgr;
private Date hiredate;
private double sal;
private double comm;
// int deptno;
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public double getComm() {
return comm;
}
public void setComm(double comm) {
this.comm = comm;
}
// public int getDeptno() {
// return deptno;
// }
// public void setDeptno(int deptno) {
// this.deptno = deptno;
// }
@Override
public String toString() {
return "Emp [empno=" + empno + ", ename=" + ename + ", job=" + job + ", mgr=" + mgr + ", hiredate=" + hiredate
+ ", sal=" + sal + ", comm=" + comm + ", dept=" + dept + "]";
}
}
我注释的部分就是那位那位很懒的博主所描述的不全的部分,因为很多什么我们要查的对象是有关联关系的
然后是dept实体对象
package test.bean;
public class Dept {
private int deptno;
private String dname;
private String loc;
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
}
}
这个就没什么好讲的了
接口我就不写了
package test.dao.imp;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import qin.common.ProcessingCenter;
import test.DBHelper;
import test.bean.Dept;
import test.bean.Emp;
import test.dao.EmpDao;
import test.dao.ProxyObjects;
public class EmpDaoImpl extends ProxyObjects implements EmpDao {
/*
*数字代表传入参数
*返回的是一个MAP集合 key(int)对应传出参数的个数(按序)
*1代表普通类型 2代表对象类型 3代表集合类型
*
*字母代表传出参数
*c代表游标
*s代表String
*i代表Integer
*o代表double
*d代表data
*/
// 测试 sql 更具id获取对象
@Override
public Emp finEmp(int id) throws Exception {
String SQL="select * from emp where empno=? ";
List list = (List) pr.executefindsql(SQL,Emp.class);
return list.get(0);
}
// 测试 sql 更新操作
@Override
public int updateEmp(String ename, int id) throws Exception {
// TODO Auto-generated method stub
String SQL = "update emp set ename = ? where empno = ?";
return pr.executeUpdatesql(SQL);
}
// 测试存储过程 根据编号获取对象
@Override
public Emp getEmpbyid(int id) throws SQLException {
// TODO Auto-generated method stub
String SQL="{call getEmpbyid({1},{c})}";
Map map = pr.execute(SQL, Emp.class);
List list = (List) map.get(0);
return list.get(0);
}
// 测试存储过程 根据编号 获取集合
@Override
public List
这里之所以用map集合是考虑到存储过程可以输出多个值的原因
而之所以结果集要传入calss是因为考虑到过程可以输出多个结果集的原因
package test.dao;
import java.sql.Connection;
import test.common.ProcessingCenter;
import test.common.utils.DBHelper;
//代理对象 名字随便取都可以
public class ProxyObjects {
//处理中心对象
public ProcessingCenter pr;
//提供一个获取Connection对象的方法 方法名称一定为getCon
public Connection getCon(){
Connection con=DBHelper.getCon();
return con;
}
}
提供一个getcon方法这样我们就可以将这个jar包和现在的主流框架一起使用了哈哈有木有很激动
package test.dao.imp;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import qin.common.ProcessingCenter;
import test.DBHelper;
import test.bean.Dept;
import test.bean.Emp;
import test.dao.EmpDao;
import test.dao.ProxyObjects;
public class EmpDaoImpl extends ProxyObjects implements EmpDao {
/*
*数字代表传入参数
*返回的是一个MAP集合 key(int)对应传出参数的个数(按序)
*1代表普通类型 2代表对象类型 3代表集合类型
*
*字母代表传出参数
*c代表游标
*s代表String
*i代表Integer
*o代表double
*d代表data
*/
// 测试 sql 更具id获取对象
@Override
public Emp finEmp(int id) throws Exception {
String SQL="select * from emp where empno=? ";
List list = (List) pr.executefindsql(SQL,Emp.class);
return list.get(0);
}
// 测试 sql 更新操作
@Override
public int updateEmp(String ename, int id) throws Exception {
// TODO Auto-generated method stub
String SQL = "update emp set ename = ? where empno = ?";
return pr.executeUpdatesql(SQL);
}
// 测试存储过程 根据编号获取对象
@Override
public Emp getEmpbyid(int id) throws SQLException {
// TODO Auto-generated method stub
String SQL="{call getEmpbyid({1},{c})}";
Map map = pr.execute(SQL, Emp.class);
List list = (List) map.get(0);
return list.get(0);
}
// 测试存储过程 根据编号 获取集合
@Override
public List> getListbyid(int id) throws SQLException {
// TODO Auto-generated method stub
String SQL="{call getEmpbyid({1},{c})}";
return (List>) pr.execute(SQL).get(0);
}
// 测试存储过程 根据用户名称获取对象集合
@Override
public List getEmpListByEname(String ename) throws SQLException {
// TODO Auto-generated method stub
String SQL="{call getEmpListByEname({1},{c})}";
Map execute = pr.execute(SQL,Emp.class);
return (List) execute.get(0);
}
// 测试存储过程 添加对象
@Override
public void addEmp(Emp emp) throws SQLException {
// TODO Auto-generated method stub
String SQL="{call addEmp({2})}";
//如果想传入一个对象进行添加必须在数据库创建对应数据类型
//第一个为对象类型,第二个为集合类型 第三个为关联字段 如果关联字段不同 以被关联对象的关联字段为准 这里的deptno为dept对象中的管理字段
String[] li={"EMPOBJ","EMPLIST","deptno"};
pr.execute(li, SQL);
}
// 测试存储过程 添加集合
@Override
public void addEmps(List list) throws SQLException {
// TODO Auto-generated method stub
String SQL="{call addEmp({3})}";
//如果想传入一个对象进行添加必须在数据库创建对应数据类型
//第一个为对象类型,第二个为集合类型 第三个为关联字段以 如果关联字段不同 以被关联对象的关联字段为准 这里的deptno为dept对象中的管理字段
String[] li={"EMPOBJ","EMPLIST","deptno"};
pr.execute(li, SQL);
}
// 测试存储过程 添加多个类型入参
@Override
public void addLists(Emp emp, int w, List list) throws SQLException {
// TODO Auto-generated method stub
String SQL="{call ADDOBJ({2},{1},{3})}";
//如果想传入一个对象进行添加必须在数据库创建对应数据类型
//第一个为对象类型,第二个为集合类型 第三个为关联字段以 如果关联字段不同 以被关联对象的关联字段为准 这里的deptno为dept对象中的管理字段
String[] li={"EMPOBJ","EMPLIST","deptno"};
String[] lis={"EMPOBJ","EMPLIST"};
List arry=new ArrayList();
arry.add(li);
arry.add(lis);
pr.execute(arry, SQL);
}
// 测试存储过程 根据id获取String类型
@Override
public String getNameById(int id) throws SQLException {
// TODO Auto-generated method stub
String sql="{call getname({1},{s})}";
return (String) pr.execute(sql).get(0);
}
// 测试存储过程 根据id获取Integer类型
@Override
public Integer getMgrById(int id) throws SQLException {
// TODO Auto-generated method stub
String sql="{call getmgr({1},{i})}";
return (Integer) pr.execute(sql).get(0);
}
// 测试存储过程 根据id获取double类型
@Override
public double getSalById(int id) throws SQLException {
// TODO Auto-generated method stub
String sql="{call getsal({1},{o})}";
return (double) pr.execute(sql).get(0);
}
// 测试存储过程 根据id获取DateE类型
@Override
public Date getHiredateById(int id) throws SQLException {
// TODO Auto-generated method stub
String sql="{call gethiredate({1},{d})}";
return (Date) pr.execute(sql).get(0);
}
}
还有两个附属工具类 一个解析结果集的BeanUtils类和一个类型识别的枚举BataType类
首先是枚举BataType类
package test.common.utils;
public enum BataType {
//枚举类型
String("java.lang.String"),BigDecimal("java.math.BigDecimal"),Date("java.sql.Timestamp");
private String name;
//构造方法
private BataType(String name) {
this.name = name;
}
//根据name值获取枚举类型
public static BataType getName(String name) {
for (BataType c : BataType .values()) {
if (c.name .equals(name)){
return c;
}
}
return null;
}
}
接着是解析结果集的BeanUtils对象
package qin.common.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class BeanUtils {
// 将结果集装配进对象返回对象集合
public static List
这里我们用cglib动态代理实现AOP拦截
package test.common.proxy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import test.common.ProcessingCenter;
public class CglibProxy implements MethodInterceptor{
private Object target;
//生成代理对象
public Object getintercept(Object target){
this.target=target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
//切面逻辑 这个拦截器的目的是将目标对象的参数写入数据处理中心(ProcessingCenter)并注入进目标对象
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
Class> superclass = target.getClass().getSuperclass();
Field field=superclass.getDeclaredField("pr");
ProcessingCenter re =new ProcessingCenter(args,superclass);
field.set(target, re);
Object ret;
ret=method.invoke(target, args);
return ret;
}
}
OK大功告成
不过还有一些类型没戏 以后慢慢写
常用的都已经写了
接下来是存储过程
create or replace procedure getEmpbyid (ids in number,O_RES OUT SYS_REFCURSOR)
as
begin
OPEN O_RES FOR
SELECT * from emp t left join dept d on t.deptno = d.deptno where t.empno= ids;
end;
create or replace procedure getEmpListByEname (ids in nvarchar2,O_RES OUT SYS_REFCURSOR)
as
begin
OPEN O_RES FOR
SELECT * from emp t left join dept d on t.deptno = d.deptno where t.ename= ids;
end;
--自定义对象类型
CREATE OR REPLACE TYPE EMPOBJ AS OBJECT (
EMPNO NUMBER(4),
ENAME NVARCHAR2(10),
JOB NVARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2)
)
--自定义集合类型
CREATE OR REPLACE TYPE EMPLIST AS TABLE OF EMPOBJ
create or replace procedure addEmp(i_orders IN EMPLIST)
as
ctcOrder EMPOBJ:=i_orders(1);
begin
INSERT INTO EMP
(EMPNO, ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO)
VALUES
(ctcOrder.EMPNO,ctcOrder.ENAME,ctcOrder.JOB,ctcOrder.MGR,ctcOrder.HIREDATE,ctcOrder.SAL,ctcOrder.COMM, ctcOrder.DEPTNO);
exception when others then
raise;
end;
create or replace procedure getname (ids in number,namea out nvarchar2)
as
begin
SELECT ENAME into namea from emp where empno= ids;
end;
create or replace procedure getmgr (ids in number,mgr out number)
as
begin
SELECT MGR into mgr from emp where empno= ids;
end;
create or replace procedure getsal (ids in number,sals out number)
as
begin
SELECT SAL into sals from emp where empno= ids;
end;
create or replace procedure gethiredate (ids in number,hiredates out varchar2)
as
begin
SELECT HIREDATE into hiredates from emp where empno= ids;
end;
然后是我们的test测试
package test;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import qin.common.proxy.CglibProxy;
import test.bean.Emp;
import test.dao.EmpDao;
import test.dao.imp.EmpDaoImpl;
public class Test {
public static void main(String[] args) throws SQLException, Exception {
Emp emp = null;
// 获取增强后的目标对象 ????
EmpDao dao = (EmpDao) new CglibProxy().getintercept(new EmpDaoImpl());
// 测试查询sql String sql="select * from emp where empno=? ";
emp = dao.finEmp(7369);
System.out.println(emp);
// 测试更新sql String SQL = "update emp set ename = ? where empno = ?";
int updateEmp = dao.updateEmp("xiaohei", 1111);
System.out.println(updateEmp);
// 测试存储过程 根据编号获取对象
emp = dao.getEmpbyid(7369);
System.out.println(emp);
// 测试存储过程 根据编号 获取集合
List> list = dao.getListbyid(7369);
System.out.println(list);
// 测试存储过程 根据用户名称获取对象集合 ????
List empListByEname = dao.getEmpListByEname("SMITH");
System.out.println(empListByEname);
// 测试存储过程 添加对象
emp.setEmpno(1224);
// dao.addEmp(emp);
// 测试存储过程 添加集合
List listEmp = new ArrayList();
listEmp.add(emp);
// dao.addEmps(listEmp);
// 测试存储过程 添加多个类型入参
// dao.addLists(emp, 1, listEmp);
// 测试存储过程 根据id获取String类型
String nameById = dao.getNameById(7369);
System.out.println(nameById);
// 测试存储过程 根据id获取Integer类型
Integer mgrById = dao.getMgrById(7369);
System.out.println(mgrById);
// 测试存储过程 根据id获取double类型
double salById = dao.getSalById(7369);
System.out.println(salById);
// 测试存储过程 根据id获取DateE类型
Date hiredateById = dao.getHiredateById(7369);
System.out.println(hiredateById);
}
}
在来看数据库
想想以后调用存储过程是多么的简单 一句话代码就可以啦