databasepersistencemanager.java

来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 1,245 行 · 第 1/3 页

JAVA
1,245
字号
        //boolean update = exists(state.getId());        String sql = (update) ? nodeStateUpdateSQL : nodeStateInsertSQL;        try {            ByteArrayOutputStream out =                    new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);            // serialize node state            Serializer.serialize(state, out);            // we are synchronized on this instance, therefore we do not            // not have to additionally synchronize on the sql statement            executeStmt(sql, new Object[]{out.toByteArray(), state.getNodeId().toString()});            // there's no need to close a ByteArrayOutputStream            //out.close();        } catch (Exception e) {            String msg = "failed to write node state: " + state.getNodeId();            log.error(msg, e);            throw new ItemStateException(msg, e);        }    }    /**     * {@inheritDoc}     * <p/>     * This method uses shared <code>PreparedStatement</code>s which must     * be executed strictly sequentially. Because this method synchronizes on     * the persistence manager instance there is no need to synchronize on the     * shared statement. If the method would not be sychronized the shared     * statements would have to be synchronized.     */    public synchronized void store(PropertyState state)            throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        // check if insert or update        boolean update = state.getStatus() != ItemState.STATUS_NEW;        //boolean update = exists(state.getId());        String sql = (update) ? propertyStateUpdateSQL : propertyStateInsertSQL;        try {            ByteArrayOutputStream out =                    new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);            // serialize property state            Serializer.serialize(state, out, blobStore);            // we are synchronized on this instance, therefore we do not            // not have to additionally synchronize on the sql statement            executeStmt(sql, new Object[]{out.toByteArray(), state.getPropertyId().toString()});            // there's no need to close a ByteArrayOutputStream            //out.close();        } catch (Exception e) {            String msg = "failed to write property state: " + state.getPropertyId();            log.error(msg, e);            throw new ItemStateException(msg, e);        }    }    /**     * {@inheritDoc}     */    public synchronized void destroy(NodeState state)            throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        try {            // we are synchronized on this instance, therefore we do not            // not have to additionally synchronize on the sql statement            executeStmt(nodeStateDeleteSQL, new Object[]{state.getNodeId().toString()});        } catch (Exception e) {            String msg = "failed to delete node state: " + state.getNodeId();            log.error(msg, e);            throw new ItemStateException(msg, e);        }    }    /**     * {@inheritDoc}     */    public synchronized void destroy(PropertyState state)            throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        // make sure binary values (BLOBs) are properly removed        InternalValue[] values = state.getValues();        if (values != null) {            for (int i = 0; i < values.length; i++) {                InternalValue val = values[i];                if (val != null) {                    if (val.getType() == PropertyType.BINARY) {                        BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();                        // delete internal resource representation of BLOB value                        blobVal.delete(true);                        // also remove from BLOBStore                        String blobId = blobStore.createId(state.getPropertyId(), i);                        try {                            blobStore.remove(blobId);                        } catch (Exception e) {                            log.warn("failed to remove from BLOBStore: " + blobId, e);                        }                    }                }            }        }        try {            // we are synchronized on this instance, therefore we do not            // not have to additionally synchronize on the sql statement            executeStmt(propertyStateDeleteSQL, new Object[]{state.getPropertyId().toString()});        } catch (Exception e) {            String msg = "failed to delete property state: " + state.getPropertyId();            log.error(msg, e);            throw new ItemStateException(msg, e);        }    }    /**     * {@inheritDoc}     */    public NodeReferences load(NodeReferencesId targetId)            throws NoSuchItemStateException, ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        synchronized (nodeReferenceSelectSQL) {            ResultSet rs = null;            InputStream in = null;            try {                Statement stmt = executeStmt(                        nodeReferenceSelectSQL, new Object[]{targetId.toString()});                rs = stmt.getResultSet();                if (!rs.next()) {                    throw new NoSuchItemStateException(targetId.toString());                }                in = rs.getBinaryStream(1);                NodeReferences refs = new NodeReferences(targetId);                Serializer.deserialize(refs, in);                return refs;            } catch (Exception e) {                if (e instanceof NoSuchItemStateException) {                    throw (NoSuchItemStateException) e;                }                String msg = "failed to read node references: " + targetId;                log.error(msg, e);                throw new ItemStateException(msg, e);            } finally {                closeStream(in);                closeResultSet(rs);            }        }    }    /**     * {@inheritDoc}     * <p/>     * This method uses shared <code>PreparedStatement</code>s which must     * be executed strictly sequentially. Because this method synchronizes on     * the persistence manager instance there is no need to synchronize on the     * shared statement. If the method would not be sychronized the shared     * statements would have to be synchronized.     */    public synchronized void store(NodeReferences refs)            throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        // check if insert or update        boolean update = exists(refs.getId());        String sql = (update) ? nodeReferenceUpdateSQL : nodeReferenceInsertSQL;        try {            ByteArrayOutputStream out =                    new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);            // serialize references            Serializer.serialize(refs, out);            // we are synchronized on this instance, therefore we do not            // not have to additionally synchronize on the sql statement            executeStmt(sql, new Object[]{out.toByteArray(), refs.getId().toString()});            // there's no need to close a ByteArrayOutputStream            //out.close();        } catch (Exception e) {            String msg = "failed to write node references: " + refs.getId();            log.error(msg, e);            throw new ItemStateException(msg, e);        }    }    /**     * {@inheritDoc}     */    public synchronized void destroy(NodeReferences refs)            throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        try {            // we are synchronized on this instance, therefore we do not            // not have to additionally synchronize on the sql statement            executeStmt(nodeReferenceDeleteSQL, new Object[]{refs.getId().toString()});        } catch (Exception e) {            String msg = "failed to delete node references: " + refs.getId();            log.error(msg, e);            throw new ItemStateException(msg, e);        }    }    /**     * {@inheritDoc}     */    public boolean exists(NodeId id) throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        synchronized (nodeStateSelectExistSQL) {            ResultSet rs = null;            try {                Statement stmt = executeStmt(nodeStateSelectExistSQL, new Object[]{id.toString()});                rs = stmt.getResultSet();                // a node state exists if the result has at least one entry                return rs.next();            } catch (Exception e) {                String msg = "failed to check existence of node state: " + id;                log.error(msg, e);                throw new ItemStateException(msg, e);            } finally {                closeResultSet(rs);            }        }    }    /**     * {@inheritDoc}     */    public boolean exists(PropertyId id) throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        synchronized (propertyStateSelectExistSQL) {            ResultSet rs = null;            try {                Statement stmt = executeStmt(                        propertyStateSelectExistSQL, new Object[]{id.toString()});                rs = stmt.getResultSet();                // a property state exists if the result has at least one entry                return rs.next();            } catch (Exception e) {                String msg = "failed to check existence of property state: " + id;                log.error(msg, e);                throw new ItemStateException(msg, e);            } finally {                closeResultSet(rs);            }        }    }    /**     * {@inheritDoc}     */    public boolean exists(NodeReferencesId targetId) throws ItemStateException {        if (!initialized) {            throw new IllegalStateException("not initialized");        }        synchronized (nodeReferenceSelectExistSQL) {            ResultSet rs = null;            try {                Statement stmt = executeStmt(                        nodeReferenceSelectExistSQL, new Object[]{targetId.toString()});                rs = stmt.getResultSet();                // a reference exists if the result has at least one entry                return rs.next();            } catch (Exception e) {                String msg = "failed to check existence of node references: "                        + targetId;                log.error(msg, e);                throw new ItemStateException(msg, e);            } finally {                closeResultSet(rs);            }        }    }    //----------------------------------< misc. helper methods & overridables >    /**     * Initializes the database connection used by this persistence manager.     * <p>     * Subclasses should normally override the {@link #getConnection()}     * method instead of this one. The default implementation calls     * {@link #getConnection()} to get the database connection and disables     * the autocommit feature.     *     * @throws Exception if an error occurs     */    protected void initConnection() throws Exception {        con = getConnection();        con.setAutoCommit(false);    }    /**     * Abstract factory method for creating a new database connection. This     * method is called by {@link #init(PMContext)} when the persistence     * manager is started. The returned connection should come with the default     * JDBC settings, as the {@link #init(PMContext)} method will explicitly     * set the <code>autoCommit</code> and other properties as needed.     * <p>     * Note that the returned database connection is kept during the entire     * lifetime of the persistence manager, after which it is closed by     * {@link #close()} using the {@link #closeConnection(Connection)} method.     *     * @return new connection     * @throws Exception if an error occurs     */    protected Connection getConnection() throws Exception {        throw new UnsupportedOperationException("Override in a subclass!");    }    /**     * Closes the given database connection. This method is called by     * {@link #close()} to close the connection acquired using     * {@link #getConnection()} when the persistence manager was started.     * <p>     * The default implementation just calls the {@link Connection#close()}     * method of the given connection, but subclasses can override this     * method to provide more extensive database and connection cleanup.     *     * @param connection database connection     * @throws Exception if an error occurs     */    protected void closeConnection(Connection connection) throws Exception {        connection.close();    }    /**     * Re-establishes the database connection. This method is called by     * {@link #store(ChangeLog)} and {@link #executeStmt(String, Object[])}     * after a <code>SQLException</code> had been encountered.     * @return true if the connection could be successfully re-established,     *         false otherwise.     */    protected synchronized boolean reestablishConnection() {        // in any case try to shut down current connection        // gracefully in order to avoid potential memory leaks        // close shared prepared statements        for (Iterator it = preparedStatements.values().iterator(); it.hasNext(); ) {            PreparedStatement stmt = ((PreparedStatement) it.next());            if (stmt != null) {                try {                    stmt.close();                } catch (SQLException se) {                    // ignored, see JCR-765                }            }        }        try {            closeConnection(con);        } catch (Exception ignore) {        }        // sleep for a while to give database a chance        // to restart before a reconnect is attempted        try {            Thread.sleep(SLEEP_BEFORE_RECONNECT);        } catch (InterruptedException ignore) {        }        // now try to re-establish connection        try {            initConnection();            initPreparedStatements();            return true;        } catch (Exception e) {            log.error("failed to re-establish connection", e);            // reconnect failed            return false;        }    }    /**     * Executes the given SQL statement with the specified parameters.     * If a <code>SQLException</code> is encountered and     * <code>autoReconnect==true</code> <i>one</i> attempt is made to re-establish     * the database connection and re-execute the statement.     *     * @param sql    statement to execute     * @param params parameters to set     * @return the <code>Statement</code> object that had been executed     * @throws SQLException if an error occurs     */    protected Statement executeStmt(String sql, Object[] params)            throws SQLException {        int trials = autoReconnect ? 2 : 1;        while (true) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?