Java 如何从jdbc调用存储函数?
我正在使用自定义标记创建一个登录页面,在下面的代码中,我希望执行一个存储的oracle函数,该函数将使用2个参数(名称、密码)进行身份验证并返回一个数字。但是当我编译下面的代码时,它给出了一个错误,即(find:int)不兼容类型。请告诉我哪里出了问题?我调用函数是否正确Java 如何从jdbc调用存储函数?,java,oracle,jdbc,Java,Oracle,Jdbc,我正在使用自定义标记创建一个登录页面,在下面的代码中,我希望执行一个存储的oracle函数,该函数将使用2个参数(名称、密码)进行身份验证并返回一个数字。但是当我编译下面的代码时,它给出了一个错误,即(find:int)不兼容类型。请告诉我哪里出了问题?我调用函数是否正确 package pack.java; import pack.java.MyModel; import java.io.*; import java.lang.*; import javax.servlet.*; import
package pack.java;
import pack.java.MyModel;
import java.io.*;
import java.lang.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.sql.*;
public class MyController extends TagSupport
{
HttpServletRequest request;
HttpServletResponse response;
public int doStartTag()throws JspException
{
request = (HttpServletRequest)pageContext.getRequest();
response = (HttpServletResponse)pageContext.getResponse();
return EVAL_PAGE;
}
public void check()
{
HttpSession mysession = request.getSession();
Connection con;
CallableStatement stmt;
JspWriter out = pageContext.getOut();
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(ClassNotFoundException ex) {}
try {
String aa = (String)MyModel.name.trim();
String bb = (String)MyModel.pass.trim();
con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","gaurav","oracle");
stmt = con.prepareCall("select usercheck1(?,?) from dual");
stmt.setString(1, aa);
stmt.setString(2, bb);
rs = stmt.executeQuery();
try {
while (rs.next()) {
String empid = rs.getString (1);
mysession.setAttribute("user", empid);
if (empid != null) {
response.sendRedirect("/Myjsp/selectaction.jsp");
}
else
out.println("InValid User");
}
}
catch(Exception ex) {}
}
catch(SQLException ex) {}
}
public int doEndTag() throws JspException {
check();
return EVAL_PAGE;
}
}
下面是存储的函数
create or replace function usercheck1
(uname varchar2, upass varchar2)
return number
as
numb number;
begin
select (employe_id)
into numb
from record
where name = uname
and password = upass;
return numb;
end usercheck1;
/
使用下面的语句执行函数
select usercheck1 ('ghg','aa') from dual;
executeUpdate()
返回int
,有关更多详细信息,请参阅。我相信您正在期待一个结果集
换线以下
rs=stmt.executeUpdate();
到
rs=stmt.executeQuery()代码>
请参阅以获取更多信息。首先,您说程序返回一个数字,但您的代码期望返回一个字符串的结果集?
无论如何,假设您的proc返回int。
更改这些行
stmt=con.prepareCall("call usercheck1(?,?)");
stmt.setString(1,aa);
stmt.setString(2,bb);
rs=stmt.executeUpdate();
到
如果您实际上希望从proc得到一个字符串,那么更改
到
结果集用于游标,需要您指定out参数。
希望有帮助
如果您使用的是较新版本的oracle>=9i,则可能需要使用begin-end语法 要执行函数,规范的方法是使用。这是PreparedStatement
的一个特例(子类)
此外,必须使用以下方法之一指定正确的输出参数类型。一旦调用完成(),就可以从语句本身提取输出值。不是通过结果集
所有这些都会导致以下情况:
CallableStatement stmt = con.prepareCall("{? = call usercheck1(?, ?)}");
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Prepare a `call`
stmt.registerOutParameter(1, Types.INTEGER);
# Setup out parameter type ^^^^^^^^^^^^^
stmt.setString(2,aa);
stmt.setString(3,bb);
stmt.execute();
# ^^^^^^^
# execute the statement
int output = stmt.getInt(1);
# ^^^^^^^^^^^
# Extract the result from the statement itself
另一种完全不同的方法是实际使用SELECT
查询来调用函数。这是OP在问题中提出的建议。这样,您可以像往常一样使用ResultSet
来提取值:
PreparedStatement stmt = con.prepareStatement("SELECT usercheck1(?, ?) FROM DUAL");
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Prepare a statement
stmt.setString(2,aa);
stmt.setString(3,bb);
ResultSet rs = stmt.executeQuery();
# ^^^^^^^^^^^^
# execute the query
while(rs.next()) {
int output = rs.getInt(1);
# ^^^^^^^^^
# Extract the result from the `ResultSet`
# ...
# do whatever you want with the data
}
其他人建议通过select语句运行查询,但如果函数执行任何DML,则会引发异常。使用CallableStatement是最好的选择。这里有一个使用JPA的更现代的解决方案(javax.persistence.EntityManager
):
以下是指示解决方案使用的库版本的主要依赖项:
compile 'com.oracle:ojdbc6:11.2.0.4.0'
compile 'org.hibernate:hibernate-core:5.4.7.Final'
compile 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final'
作为doWork()
和使用getXxx(1)
分配存储函数结果的替代方法,您可以使用
在科特林
以下是Kotlin中的解决方案(并使用doReturningWork
):
在哪一行报告错误?它说不兼容的类型find:int,required:java.sql.ResultSet,在rs=stmt.executeUpdate()行;在不久的将来,请转到查看您的格式。感谢您的输入,但是当我尝试通过更改代码来执行代码时,您建议代码不起作用,登录失败,因为我认为该函数未执行。我正在更新我创建的函数,请检查可能出现的问题。除非你告诉我发生了什么以及你现在正在做什么,否则我无法告诉你出现了什么问题。也许你应该重新发布你的新代码……另外,尝试将你的可调用sql代码更改为“begin:=usercheck1(?);end;”这是新的oracle 9i语法。我已经重新发布了代码,当我尝试登录页面时,不会重定向。我使用了这两个语句(begin?:=usercheck1(?,);end;和{=callusercheck1(?,)}),但都不起作用。。。我正在使用oracle 10G,感谢它奏效了。。虽然我不想使用query stmt=con.prepareCall(“从dual中选择usercheck1(?,));这不可能是对的。。。CallableStatement不是只针对过程而不是函数吗?否则,您将如何获得第0个参数位置的函数返回值?实际上,请参见:为什么需要大括号?当使用DUAL
中的时,您无法使用数据编辑执行过程(仅选择)。
PreparedStatement stmt = con.prepareStatement("SELECT usercheck1(?, ?) FROM DUAL");
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Prepare a statement
stmt.setString(2,aa);
stmt.setString(3,bb);
ResultSet rs = stmt.executeQuery();
# ^^^^^^^^^^^^
# execute the query
while(rs.next()) {
int output = rs.getInt(1);
# ^^^^^^^^^
# Extract the result from the `ResultSet`
# ...
# do whatever you want with the data
}
@PersistenceContext
private EntityManager entityManager;
. . .
final int myResult;
Session session = entityManager.unwrap(Session.class);
session.doWork(connection -> {
try (CallableStatement function =
connection.prepareCall("{ ? = call usercheck1(?, ?) }")) {
function.registerOutParameter(1, Types.INTEGER);
function.setString(2, aa);
function.setString(3, bb);
function.execute();
myResult = function.getInt(1);
}
} );
compile 'com.oracle:ojdbc6:11.2.0.4.0'
compile 'org.hibernate:hibernate-core:5.4.7.Final'
compile 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final'
@PersistenceContext
lateinit var entityManager: EntityManager
. . .
val session : Session = entityManager.unwrap(Session::class.java)
var myResult = session.doReturningWork { connection: Connection ->
connection.prepareCall("{ ? = call usercheck1(?, ?) }").use { function ->
function.registerOutParameter(1, Types.INTEGER)
function.setString(2, aa)
function.setString(3, bb)
function.execute()
return@doReturningWork function.getInt(1)
}
}