java.sql.SQLSyntaxErrorException:ORA-01745:托管bean中的主机/绑定变量名称无效

时间:2012-04-08 17:35:30

标签: java sql oracle

我有基于此tutorial的托管bean。

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
// or import javax.faces.bean.SessionScoped;
import javax.inject.Named;
/* include SQL Packages */
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import javax.annotation.Resource;
import javax.faces.component.UICommand;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
// or import javax.faces.bean.ManagedBean; 
import javax.faces.event.ActionEvent;

import org.glassfish.osgicdi.OSGiService;

// source http://balusc.blogspot.com/2008/10/effective-datatable-paging-and-sorting.html

@Named("SessionsController")
@SessionScoped
public class Sessions implements Serializable {

    /* Call the Oracle JDBC Connection driver */
    @Resource(name = "jdbc/Oracle")
    private DataSource ds;
    // Data.
    private List<ActiveSessionObj> dataList;
    private int totalRows;
    // Paging.
    private int firstRow;
    private int rowsPerPage;
    private int totalPages;
    private int pageRange;
    private Integer[] pages;
    private int currentPage;
    // Sorting.
    private String sortField;
    private boolean sortAscending;

    private static class ActiveSessionObj {

        /* Oracle table structure
        CREATE TABLE ACTIVESESSIONSLOG(
        ASESSIONID VARCHAR2(30 ) NOT NULL,
        USERID VARCHAR2(30 ),
        ACTIVITYSTART TIMESTAMP(6),
        ACTIVITYEND TIMESTAMP(6),
        ACTIVITY CLOB
        )
         */
        private String aSessionID;
        private String userID;
        private Date activityStart;
        private Date activityEnd;
        private String activity;

        public ActiveSessionObj(String aSessionID, String userID, Date activityStart, Date activityEnd, String activity) {
            this.aSessionID = aSessionID;
            this.userID = userID;
            this.activityStart = activityStart;
            this.activityEnd = activityEnd;
            this.activity = activity;
        }

        public String getaSessionID() {
            return aSessionID;
        }

        public void setaSessionID(String aSessionID) {
            this.aSessionID = aSessionID;
        }

        public String getActivity() {
            return activity;
        }

        public void setActivity(String activity) {
            this.activity = activity;
        }

        public Date getActivityEnd() {
            return activityEnd;
        }

        public void setActivityEnd(Date activityEnd) {
            this.activityEnd = activityEnd;
        }

        public Date getActivityStart() {
            return activityStart;
        }

        public void setActivityStart(Date activityStart) {
            this.activityStart = activityStart;
        }

        public String getUserID() {
            return userID;
        }

        public void setUserID(String userID) {
            this.userID = userID;
        }

        private ActiveSessionObj() {
            throw new UnsupportedOperationException("Not yet implemented");
        }
    }

    // Constructors -------------------------------------------------------------------------------
    public Sessions() {
        // Set default values somehow (properties files?).
        rowsPerPage = 10; // Default rows per page (max amount of rows to be displayed at once).
        pageRange = 10; // Default page range (max amount of page links to be displayed at once).
        sortField = "ASESSIONID"; // Default sort field.
        sortAscending = true; // Default sort direction.
    }

    // Paging actions -----------------------------------------------------------------------------
    public void pageFirst() {
        page(0);
    }

    public void pageNext() {
        page(firstRow + rowsPerPage);
    }

    public void pagePrevious() {
        page(firstRow - rowsPerPage);
    }

    public void pageLast() {
        page(totalRows - ((totalRows % rowsPerPage != 0) ? totalRows % rowsPerPage : rowsPerPage));
    }

    public void page(ActionEvent event) {
        page(((Integer) ((UICommand) event.getComponent()).getValue() - 1) * rowsPerPage);
    }

    private void page(int firstRow) {
        this.firstRow = firstRow;
        loadDataList(); // Load requested page.
    }

    // Sorting actions ----------------------------------------------------------------------------
    public void sort(ActionEvent event) {
        String sortFieldAttribute = (String) event.getComponent().getAttributes().get("sortField");

        // If the same field is sorted, then reverse order, else sort the new field ascending.
        if (sortField.equals(sortFieldAttribute)) {
            sortAscending = !sortAscending;
        } else {
            sortField = sortFieldAttribute;
            sortAscending = true;
        }

        pageFirst(); // Go to first page and load requested page.
    }

    // Loaders ------------------------------------------------------------------------------------
    private void loadDataList() {

        // Load list and totalCount.
        try {
            dataList = list(firstRow, rowsPerPage, sortField, sortAscending);
            totalRows = count(); //count the tablerows
        } catch (Exception e) {
            throw new RuntimeException(e); // Handle it yourself.
        }

        // Set currentPage, totalPages and pages.
        currentPage = (totalRows / rowsPerPage) - ((totalRows - firstRow) / rowsPerPage) + 1;
        totalPages = (totalRows / rowsPerPage) + ((totalRows % rowsPerPage != 0) ? 1 : 0);
        int pagesLength = Math.min(pageRange, totalPages);
        pages = new Integer[pagesLength];

        // firstPage must be greater than 0 and lesser than totalPages-pageLength.
        int firstPage = Math.min(Math.max(0, currentPage - (pageRange / 2)), totalPages - pagesLength);

        // Create pages (page numbers for page links).
        for (int i = 0; i < pagesLength; i++) {
            pages[i] = ++firstPage;
        }
    }

    // Getters ------------------------------------------------------------------------------------
    public List<ActiveSessionObj> getDataList() {
        if (dataList == null) {
            loadDataList(); // Preload page for the 1st view.
        }
        return dataList;
    }

    public int getTotalRows() {
        return totalRows;
    }

    public int getFirstRow() {
        return firstRow;
    }

    public int getRowsPerPage() {
        return rowsPerPage;
    }

    public Integer[] getPages() {
        return pages;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public int getTotalPages() {
        return totalPages;
    }

    // Setters ------------------------------------------------------------------------------------
    public void setRowsPerPage(int rowsPerPage) {
        this.rowsPerPage = rowsPerPage;
    }

    // Actions ------------------------------------------------------------------------------------
    /**
     * Returns list of ActiveSessionObj items starting at the given first index with the given row count,
     * sorted by the given sort field and sort order.
     * @param firstRow First index of rows to be returned.
     * @param rowCount Amount of rows to be returned.
     * @param sortField Field to sort the data on.
     * @param sortAscending Whether to sort data ascending or not.
     * @return list of ActiveSessionObj items starting at the given first index with the given row count,
     * sorted by the given sort field and sort order.
     * @throws DAOException If something fails at DAO level.
     */
    public List<ActiveSessionObj> list(int firstRow, int rowCount, String sortField, boolean sortAscending) throws SQLException {

        String SQL_LIST_BY_ORDER_AND_LIMIT = "SELECT * FROM ACTIVESESSIONSLOG WHERE ROWNUM >= ? AND ROWNUM <= ? ORDER BY ? ?";     

        if (ds == null) {
            throw new SQLException();
        }

        String sortDirection = sortAscending ? "ASC" : "DESC";
        String sql = String.format(SQL_LIST_BY_ORDER_AND_LIMIT, sortField, sortDirection);
        Connection conn = ds.getConnection();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<ActiveSessionObj> dataList = new ArrayList<ActiveSessionObj>();

        try {
            conn.setAutoCommit(false);
            boolean committed = false;
            preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setInt(1, firstRow);
            preparedStatement.setInt(2, rowCount);
            preparedStatement.setString(3, sortField);
            preparedStatement.setString(4, sortDirection);                   

            resultSet = preparedStatement.executeQuery();
            /* take the result from the SQL query and insert it into Array List collection */
            dataList = ActiveSessionsArrayList(resultSet);

        } catch (SQLException e) {
            throw new SQLException(e);
        } finally {
            conn.close();
        }

        return dataList;
    }

    /**
     * Returns total amount of rows in table.
     * @return Total amount of rows in table.
     * @throws DAOException If something fails at DAO level.
     */
    public int count() throws Exception {

        String SQL_COUNT = "SELECT count(*) FROM ACTIVESESSIONSLOG";

        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        int count = 0;

        try {
            Connection conn = ds.getConnection();
            preparedStatement = conn.prepareStatement(SQL_COUNT);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                count = resultSet.getInt(1);
            }
        } catch (SQLException e) {
            throw new Exception(e);
        } finally {
            //close the connection
        }

        return count;
    }

    /**
     * Map the current row of the given ResultSet to ActiveSessionObj.
     * @param resultSet The ResultSet of which the current row is to be mapped to ActiveSessionObj.
     * @return The mapped ActiveSessionObj from the current row of the given ResultSet.
     * @throws SQLException If something fails at database level.
     */
    private static ArrayList<ActiveSessionObj> ActiveSessionsArrayList(ResultSet rs) throws SQLException 
    {
        ArrayList<ActiveSessionObj> al = null;

        try
        {
            while(rs.next())
            {
                al.add(new ActiveSessionObj(
                rs.getString("ASESSIONID"),
                rs.getString("USERID"),
                timestampToDate(rs.getTimestamp("ACTIVITYSTART")),
                timestampToDate(rs.getTimestamp("ACTIVITYEND")),
                rs.getString("ACTIVITY")

                ));
            }
        }
        catch(Exception x) {x.printStackTrace();}

        return al;


        /*
        CREATE TABLE ACTIVESESSIONSLOG(
        ASESSIONID VARCHAR2(30 ) NOT NULL,
        USERID VARCHAR2(30 ),
        ACTIVITYSTART TIMESTAMP(6),
        ACTIVITYEND TIMESTAMP(6),
        ACTIVITY CLOB
        )
         */
    }
    // select all button handle
    private Map<Long, Boolean> selectedIds = new HashMap<Long, Boolean>();

    // get the list from the JSF page
    public Map<Long, Boolean> getSelectedIds() {
        return selectedIds;
    }

    // call this method from the JSF page to delete the selected rows
    public String deleteAction() {

        // do something with the selected rows
        return null;
    }

    private static Date timestampToDate(java.sql.Timestamp ts)
    {
        Date d = null;
        try
        {
            d = new Date(ts.getTime());
        }
        catch (Exception e) { e.printStackTrace(); }

        return d;
    }
}

当我在Glassfish中运行代码时,我得到了这个错误堆栈:

java.lang.RuntimeException: java.sql.SQLException: java.sql.SQLSyntaxErrorException: ORA-01745: invalid host/bind variable name

    at com.DX_57.HM_57.Sessions.loadDataList(Sessions.java:193)
    at com.DX_57.HM_57.Sessions.getDataList(Sessions.java:214)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:363)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:138)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:183)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:224)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
    at javax.faces.component.UIData.getValue(UIData.java:731)
    at javax.faces.component.UIData.getDataModel(UIData.java:1798)
    at javax.faces.component.UIData.setRowIndexWithoutRowStatePreserved(UIData.java:484)
    at javax.faces.component.UIData.setRowIndex(UIData.java:473)
    at com.sun.faces.renderkit.html_basic.TableRenderer.encodeBegin(TableRenderer.java:81)
    at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:820)
    at javax.faces.component.UIData.encodeBegin(UIData.java:1118)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1755)
    at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1757)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:402)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.sql.SQLException: java.sql.SQLSyntaxErrorException: ORA-01745: invalid host/bind variable name

    at com.DX_57.HM_57.Sessions.list(Sessions.java:289)
    at com.DX_57.HM_57.Sessions.loadDataList(Sessions.java:190)
    ... 57 more
Caused by: java.sql.SQLSyntaxErrorException: ORA-01745: invalid host/bind variable name

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884)
    at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1289)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493)
    at com.sun.gjc.spi.jdbc40.PreparedStatementWrapper40.executeQuery(PreparedStatementWrapper40.java:642)
    at com.DX_57.HM_57.Sessions.list(Sessions.java:284)
    ... 58 more

我认为SQL查询不正确或准备好的语句存在问题。这个查询的正确方法是什么?

祝福

编辑这是Oracle表:

-- TABLE ACTIVESESSIONSLOG

CREATE TABLE ACTIVESESSIONSLOG(
  ASESSIONID VARCHAR2(30 ) NOT NULL,
  USERID VARCHAR2(30 ),
  ACTIVITYSTART TIMESTAMP(6),
  ACTIVITYEND TIMESTAMP(6),
  ACTIVITY CLOB
)
/

-- ADD KEYS FOR TABLE ACTIVESESSIONSLOG

ALTER TABLE ACTIVESESSIONSLOG ADD CONSTRAINT ASESSIONID PRIMARY KEY (ASESSIONID)
/

4 个答案:

答案 0 :(得分:12)

查询是问题,或者更确切地说是查询参数。您只能绑定值,而不能绑定列名或SQL关键字。因此必须更改最后两个参数(在ORDER BY之后)。你可能已经计划好了。否则String.format没有意义。

String SQL_LIST_BY_ORDER_AND_LIMIT = "SELECT * FROM ACTIVESESSIONSLOG WHERE ROWNUM >= ? AND ROWNUM <= ? ORDER BY %s %s";

....

String sql = String.format(SQL_LIST_BY_ORDER_AND_LIMIT, sortField, sortDirection);

然后需要删除以下两行:

preparedStatement.setString(3, sortField);
preparedStatement.setString(4, sortDirection);         

答案 1 :(得分:4)

在您的查询中查找预定义的关键字,尽管您没有解决它。确保查询中的所有值都用逗号正确分隔。

我错过了一个逗号,在我弄明白之前花了我一个小时。

答案 2 :(得分:0)

似乎我没有声誉在Codo的回答中发表评论。

他的回答对我有帮助,但如果 sortField sortDirection 是可以由用户更改的参数,请注意 SQL注入

在这种情况下如何防止sql注入?什么是最好的方式?

答案 3 :(得分:0)

查询部分有问题

  1. 查询中 (IN) 或 (NOT IN) 条件值不应超过 1000 个值。
  2. 如果累积到 6(SIX) IN 条件(即所有条件下的值不应超过 6635