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 + -
显示快捷键?