大多JDBC的使用中,都将SQL语句直接嵌入到 java代码中,并有你JDBC接口将其送到数据库,由数据库解释执行。
数据库系统通过Prepared SQL来优化SQL程序。Prepared SQL有两种类型:Prepared语句和存储过程。
Prepared语句:被应用程序调用之前就被送到数据库进行解释。 好处在于:当程序中包含了相同的SQL语句时,可以调高程序的指向效率。
JDBC提供了PreparedStatement类来处理 Prepared SQL语句。
存储过程:
尽管采用了PreparedStatement ,但是SQL语句任然是和JAVA 代码混在了一起,还没有达到所需的“黑箱” 效果。
而java.sql.CallableStatement类提供了类似“黑箱”的数据库访问方式,即通过存储过程来访问。
优点:1. 在大多数数据库中,存储过程都是在数据库中进行预编译的,因此它比每次都需要进行解释的动态SQL执行速度快的多。
2.存储过程中任何语法错误能在编译时就被发现,而不是运行时才发现。
3.java开发人员只需要知道存储过程的名字,参数无需了解执行情况,如访问表的名称,表的结构等。
数据库服务器 新建存储过程:
USE [mydatabase]
GO
/****** Object: StoredProcedure [dbo].[adtd_data_proc] Script Date: 06/01/2016 16:00:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[adtd_data_proc]
(@year INT,
@lon FLOAT,
@lat FLOAT,
@dis FLOAT)
AS
begin
select intensity,longitude,latitude
from adtdreal_view a
where a.dyear<=@year and a.dyear >(@year-5) and dbo.distance(@lon,@lat,a.longitude,a.latitude)<=@dis ;
end
其中,distance是数据库中新建的函数。
USE [mydatabases]
GO
/****** Object: UserDefinedFunction [dbo].[distance] Script Date: 06/01/2016 16:02:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[distance](@lng1 FLOAT,@lat1 FLOAT,@lng2 FLOAT,@lat2 FLOAT)
returns FLOAT
as
begin
declare @R FLOAT , @a FLOAT,@b FLOAT,@s Float
select @R = 6378.137
select @a = ABS((@lat1*PI()/180.0)-(@lat2*PI()/180.0))
select @b = ABS((@lng1*PI()/180.0)-(@lng2*PI()/180.0))
select @s=2*ASIN(SQRT(POWER(SIN(@a/2),2)+(COS(@lat1*PI()/180.0)*COS(@lat2*PI()/180.0)*POWER(SIN(@b/2),2))))*@R
return @s;
end
数据库中新建好存储过程之后,项目中便可以使用了:
private PreparedStatement m_ps;
private CallableStatement m_cs;
private ResultSet m_rs;
m_cs=m_conn.prepareCall("{call dbo.adtd_data_proc(?,?,?,?)}");
m_cs.setInt(1,year);
m_cs.setFloat(2,longitude);
m_cs.setFloat(3,latitude);
m_cs.setFloat(4,f);
m_rs=m_cs.executeQuery(); // 返回ResultSet
return m_rs;
与PreparedStatement 使用的对比
String sql="select intensity,longitude,latitude from adtdreal_view a where "
+"a.dyear<=?"+"and a.dyear>?-5"
+"and dbo.distance(?,?,a.longitude,a.latitude)<=?";
System.out.println(sql);
m_ps = m_conn.prepareStatement(sql);
m_ps.setInt(1, year);
m_ps.setInt(2, year);
m_ps.setFloat(3, longitude);
m_ps.setFloat(4, latitude);
m_ps.setDouble(5,range);
m_rs=m_ps.executeQuery();
return m_rs;