Обсуждение: CallableStatement, functions and ResultSets
I hope someone can help me. And thanks ahead of time!
Here is my problem: I have a table and a function that simply performs
a select * from table. The function returns a setof table. I want to
use a CallableStatement and execute the function, but get an exception
stating "Cannot display a value of type RECORD"
Here is my table:
create table state_table
(
abbreviation char ( 2 ) unique not null,
name text not null
);
Here is the function:
CREATE OR REPLACE FUNCTION state_find () RETURNS SETOF state_table AS '
DECLARE
_aRow state_table%ROWTYPE;
BEGIN
FOR _aRow IN SELECT * FROM state_table LOOP
RETURN NEXT _aRow;
END LOOP;
RETURN;
END;
' LANGUAGE 'plpgsql';
Here is the snippet of java code:
private static void retrieveState ( final ResultSet rs ) throws
Exception
{
System.out.println
(
"Abbreviation: <" + rs.getString ( 1 ) +
"> Name: " + rs.getString ( 2 )
);
}
private static void retrieveStates ( final Connection db ) throws
Exception
{
final CallableStatement stmt =
db.prepareCall ( "{call state_find ()}" );
final ResultSet rs = stmt.executeQuery ();
while ( rs.next () )
{
retrieveState ( rs );
}
stmt.close ();
}
Here is my exception:
java.sql.SQLException: ERROR: Cannot display a value of type RECORD
at
org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:131)
at
org.postgresql.jdbc1.AbstractJdbc1Connection.ExecSQL(AbstractJdbc1Connection.java:505)
at
org.postgresql.jdbc1.AbstractJdbc1Statement.execute(AbstractJdbc1Statement.java:320)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:48)
at
org.postgresql.jdbc1.AbstractJdbc1Statement.executeQuery(AbstractJdbc1Statement.java:153)
at org.jpim.populate.Retrieve.retrieveStates(Retrieve.java:58)
at org.jpim.populate.Retrieve.main(Retrieve.java:83)
If I change my method as such:
private static void retrieveStates ( final Connection db ) throws
Exception
{
final PreparedStatement stmt =
db.prepareStatement ( "select * from state_find ()" );
final ResultSet rs = stmt.executeQuery ();
while ( rs.next () )
{
retrieveState ( rs );
}
stmt.close ();
}
It all works. I've seen on the archives that this is what one needs to
do. And that's fine by me. But my question is this: should I just use
a PreparedStatement that does "select * from state_table" or have a
function that does the "select * from table" and then use a
PreparedStatement to "select * from function()"
My gut feeling is to use a PreparedStatement with "select * from
state_table" I guess I'd really like to know which is more efficient?
And also, I'd like to know why one can't use a CallableStatement?
Thanks again!
Scot
--
Scot P. Floess - 27 Lake Royale - Louisburg, NC 27549 - 252-478-8087
Open Source Home Page
--------------------------------------
http://javapim.sourceforge.net
http://jplate.sourceforge.net
http://jwaretechniques.sourceforge.net
Open Source Project Host
-----------------------------------------------
http://sourceforge.net/projects/javapim
http://sourceforge.net/projects/jplate
http://sourceforge.net/projects/jwaretechniques
Scot,
You should definitely use the PreparedStatement, that will be much more
efficient. Going through the stored function just adds a lot of
overhead without providing any added value.
As for the CallableStatement problem. Off the top of my head I am not
sure why that isn't working.
--Barry
Scot P. Floess wrote:
> I hope someone can help me. And thanks ahead of time!
>
> Here is my problem: I have a table and a function that simply performs
> a select * from table. The function returns a setof table. I want to
> use a CallableStatement and execute the function, but get an exception
> stating "Cannot display a value of type RECORD"
>
> Here is my table:
>
> create table state_table
> (
> abbreviation char ( 2 ) unique not null,
> name text not null
> );
>
>
> Here is the function:
>
> CREATE OR REPLACE FUNCTION state_find () RETURNS SETOF state_table AS '
> DECLARE
> _aRow state_table%ROWTYPE;
>
> BEGIN
> FOR _aRow IN SELECT * FROM state_table LOOP
> RETURN NEXT _aRow;
> END LOOP;
>
> RETURN;
> END;
> ' LANGUAGE 'plpgsql';
>
> Here is the snippet of java code:
>
> private static void retrieveState ( final ResultSet rs ) throws
> Exception
> {
> System.out.println
> (
> "Abbreviation: <" + rs.getString ( 1 ) +
> "> Name: " + rs.getString ( 2 )
> );
> }
>
> private static void retrieveStates ( final Connection db ) throws
> Exception
> {
> final CallableStatement stmt =
> db.prepareCall ( "{call state_find ()}" );
>
> final ResultSet rs = stmt.executeQuery ();
>
> while ( rs.next () )
> {
> retrieveState ( rs );
> }
>
> stmt.close ();
> }
>
> Here is my exception:
>
> java.sql.SQLException: ERROR: Cannot display a value of type RECORD
>
> at
> org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:131)
> at
> org.postgresql.jdbc1.AbstractJdbc1Connection.ExecSQL(AbstractJdbc1Connection.java:505)
>
> at
> org.postgresql.jdbc1.AbstractJdbc1Statement.execute(AbstractJdbc1Statement.java:320)
>
> at
> org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:48)
>
> at
> org.postgresql.jdbc1.AbstractJdbc1Statement.executeQuery(AbstractJdbc1Statement.java:153)
>
> at org.jpim.populate.Retrieve.retrieveStates(Retrieve.java:58)
> at org.jpim.populate.Retrieve.main(Retrieve.java:83)
>
> If I change my method as such:
>
> private static void retrieveStates ( final Connection db ) throws
> Exception
> {
> final PreparedStatement stmt =
> db.prepareStatement ( "select * from state_find ()" );
> final ResultSet rs = stmt.executeQuery ();
>
> while ( rs.next () )
> {
> retrieveState ( rs );
> }
>
> stmt.close ();
> }
>
> It all works. I've seen on the archives that this is what one needs to
> do. And that's fine by me. But my question is this: should I just use
> a PreparedStatement that does "select * from state_table" or have a
> function that does the "select * from table" and then use a
> PreparedStatement to "select * from function()"
>
> My gut feeling is to use a PreparedStatement with "select * from
> state_table" I guess I'd really like to know which is more efficient?
> And also, I'd like to know why one can't use a CallableStatement?
>
> Thanks again!
>
> Scot
>
Barry:
Thanks for the response!
Your answer was what I thought to be the case. So, when is it better to
use a PL/pgSQL function versus building the SQL and using a
PreparedStatement?
Much appreciated!
Scot
Barry Lind wrote:
> Scot,
>
> You should definitely use the PreparedStatement, that will be much
> more efficient. Going through the stored function just adds a lot of
> overhead without providing any added value.
>
> As for the CallableStatement problem. Off the top of my head I am not
> sure why that isn't working.
>
> --Barry
>
> Scot P. Floess wrote:
>
>> I hope someone can help me. And thanks ahead of time!
>>
>> Here is my problem: I have a table and a function that simply
>> performs a select * from table. The function returns a setof table.
>> I want to use a CallableStatement and execute the function, but get
>> an exception stating "Cannot display a value of type RECORD"
>>
>> Here is my table:
>>
>> create table state_table
>> (
>> abbreviation char ( 2 ) unique not null,
>> name text not null
>> );
>>
>>
>> Here is the function:
>>
>> CREATE OR REPLACE FUNCTION state_find () RETURNS SETOF state_table AS '
>> DECLARE
>> _aRow state_table%ROWTYPE;
>>
>> BEGIN
>> FOR _aRow IN SELECT * FROM state_table LOOP
>> RETURN NEXT _aRow;
>> END LOOP;
>>
>> RETURN;
>> END;
>> ' LANGUAGE 'plpgsql';
>>
>> Here is the snippet of java code:
>>
>> private static void retrieveState ( final ResultSet rs ) throws
>> Exception
>> {
>> System.out.println
>> (
>> "Abbreviation: <" + rs.getString ( 1 ) +
>> "> Name: " + rs.getString ( 2 )
>> );
>> }
>>
>> private static void retrieveStates ( final Connection db ) throws
>> Exception
>> {
>> final CallableStatement stmt =
>> db.prepareCall ( "{call state_find ()}" );
>>
>> final ResultSet rs = stmt.executeQuery ();
>>
>> while ( rs.next () )
>> {
>> retrieveState ( rs );
>> }
>>
>> stmt.close ();
>> }
>> Here is my exception:
>>
>> java.sql.SQLException: ERROR: Cannot display a value of type RECORD
>>
>> at
>> org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:131)
>> at
>> org.postgresql.jdbc1.AbstractJdbc1Connection.ExecSQL(AbstractJdbc1Connection.java:505)
>>
>> at
>> org.postgresql.jdbc1.AbstractJdbc1Statement.execute(AbstractJdbc1Statement.java:320)
>>
>> at
>> org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:48)
>>
>> at
>> org.postgresql.jdbc1.AbstractJdbc1Statement.executeQuery(AbstractJdbc1Statement.java:153)
>>
>> at org.jpim.populate.Retrieve.retrieveStates(Retrieve.java:58)
>> at org.jpim.populate.Retrieve.main(Retrieve.java:83)
>>
>> If I change my method as such:
>>
>> private static void retrieveStates ( final Connection db ) throws
>> Exception
>> {
>> final PreparedStatement stmt =
>> db.prepareStatement ( "select * from state_find ()" );
>> final ResultSet rs = stmt.executeQuery ();
>>
>> while ( rs.next () )
>> {
>> retrieveState ( rs );
>> }
>>
>> stmt.close ();
>> }
>>
>> It all works. I've seen on the archives that this is what one needs
>> to do. And that's fine by me. But my question is this: should I
>> just use a PreparedStatement that does "select * from state_table" or
>> have a function that does the "select * from table" and then use a
>> PreparedStatement to "select * from function()"
>>
>> My gut feeling is to use a PreparedStatement with "select * from
>> state_table" I guess I'd really like to know which is more
>> efficient? And also, I'd like to know why one can't use a
>> CallableStatement?
>>
>> Thanks again!
>>
>> Scot
>>
>
>
>
>
--
Scot P. Floess - 27 Lake Royale - Louisburg, NC 27549 - 252-478-8087
Open Source Home Page
--------------------------------------
http://javapim.sourceforge.net
http://jplate.sourceforge.net
http://jwaretechniques.sourceforge.net
Open Source Project Host
-----------------------------------------------
http://sourceforge.net/projects/javapim
http://sourceforge.net/projects/jplate
http://sourceforge.net/projects/jwaretechniques
I am trying a simple JSTL example. I am using tomcat4.0.1, jdk1.4.1_01,
red hat 8.0, jstl 1.0 implementation from sun, postgresql 7.3.2 with jdbc
drivers pg73jdbc3.jar.
In my example I create a data source and run a query. The server responds
with a "No suitable driver" message. I have tried the same query in a
Servlet, and it works fine. Is this a driver compatibility issue? I am
pretty sure my container is finding the pgsql jdbc drivers - I have
explicitly put them in the tomcat startup classpath, and in
java_home/lib/ext.
I have attached a snippet from my jsp and exception stacktrace. If someone
can help me fix this issue, I would greatly appreaciate it.
Thanks,
Tanu
Here is my jsp:
<sql:setDataSource
var="example"
driver="org.postgresql.Driver"
url="jdbc:postgresql:pandavs"
user="username"
password="password"
/>
<sql:transaction dataSource="${example}">
<sql:query var="deejays">
SELECT * FROM category
</sql:query>
</sql:transaction>
And here is the exception stacktrace:
javax.servlet.ServletException: Error getting connection: "No suitable
driver"
at
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:471)
at org.apache.jsp.query$jsp._jspService(query$jsp.java:241)
at
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:107)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at
org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServlet.java:201)
at
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:381)
at
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:473)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:260)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:646)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:483)
at
org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:646)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:483)
at
org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at
org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2349)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:646)
at
org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:170)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:644)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:171)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:644)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:483)
at
org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:646)
at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:469)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:644)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:483)
at
org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at
org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:405)
at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:376)
at
org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:508)
at
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:518)
at java.lang.Thread.run(Thread.java:536)
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
On Mon, 2003-03-17 at 21:11, Tanu Shankar Bhatnagar wrote: > I am trying a simple JSTL example. I am using tomcat4.0.1, jdk1.4.1_01, > red hat 8.0, jstl 1.0 implementation from sun, postgresql 7.3.2 with jdbc > drivers pg73jdbc3.jar. > > Here is my jsp: > <sql:setDataSource > var="example" > driver="org.postgresql.Driver" > url="jdbc:postgresql:pandavs" > user="username" > password="password" > /> Your URL should be more like: url="jdbc:postgresql://server/db_name" Cheers Tony Grant -- www.tgds.net Library management software toolkit, redhat linux on Sony Vaio C1XD, Dreamweaver MX with Tomcat and PostgreSQL
I ran into jdbc driver not being found by tomcat issue, which I solved by putting pg73jdbc3.jar in common/lib in tomcat. Now I am trying to look up a data source through JNDI in my servlet and jstl-jsp both, but it is failing in both cases. Assuming that it has got to do with the drivers not being found, I have tried the following: 1. put the drivers in common/lib, server/lib, shared/lib and of course WEB-INF/lib 2. put the drivers in java_home/lib/ext 3. add the drivers explicitly in catalina.sh None if this worked, though I managed to change the error message from 'No suitable driver' to 'Cannot load JDBC driver class 'null''. I have followed the instructions from tomcat site to create my datasource, and to modify my web.xml appropriately. http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-datasource-examples-howto.html I am using tomcat4.0.1, jdk1.4.1_01, red hat 8.0, jstl 1.0 implementation from sun, postgresql 7.3.2 with jdbc drivers pg73jdbc3.jar. Any help on this issue will be appreciated. Thanks, Tanu ps: Tony, I did change the db url to what you suggested, but that did not make a difference. Here is the error snippet I get: java.sql.SQLException: Cannot load JDBC driver class 'null' at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:529) at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:312) at TestServlet.doGet(TestServlet.java:52) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) Code snippet from Servlet: Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); DataSource ds = (DataSource)envCtx.lookup("jdbc/test"); Connection conn = ds.getConnection(); Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(CATEGORY_SQL); while(rs.next()) { // get stuff } Code snippet from jsp: <sql:setDataSource var="example" dataSource="jdbc/test" /> <sql:transaction dataSource="${example}"> <sql:query var="deejays"> SELECT name, description FROM category </sql:query> </sql:transaction> __________________________________________________ Do you Yahoo!? Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop! http://platinum.yahoo.com