我最近在我的web應用程序中編寫了一個類,用於解析一個巨大的XML文件並向其中添加一個數據庫表。我的應用程序在Wildfly9上運行,並使用JPA和Hibernate提供程序來處理MySQL數據庫。@資源數據源破壞數據庫連接
的AS配置是非常標準的,我只是說我的數據源的conf:
<datasource jta="false" jndi-name="java:jboss/datasources/spazio_visione" pool-name="spazio_visione" enabled="true" use-ccm="false">
<connection-url>jdbc:mysql://127.0.0.1:3306/spazio_visione?zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=true</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver>mysql</driver>
<security>
<user-name>myuser</user-name>
<password>mypasswd</password>
</security>
<validation>
<validate-on-match>false</validate-on-match>
<background-validation>false</background-validation>
</validation>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
</datasource>
而且這裏是我的persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="backoffice" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/spazio_visione</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.jdbc.batch_size" value="100" />
<property name="hibernate.order_inserts" value="true" />
<property name="hibernate.order_updates" value="true" />
<!-- <property name="hibernate.show_sql" value="true"/> -->
<!-- <property name="hibernate.hbm2ddl.auto" value="validate"/> -->
</properties>
</persistence-unit>
</persistence>
一切一直工作正常,使用JPA實體管理我的領域模型。
回到我的解析器......實際上,由於很多原因,它需要使用本機JDBC查詢將數據插入到數據庫中。下面的代碼:
public class XMLFeedParser extends DefaultHandler {
@Inject Logger logger;
@Resource(lookup="java:jboss/datasources/spazio_visione") DataSource datasource;
private static final int STATEMENT_BATCH_THRESHOLD = 1000;
private MyXMLFeedItem item;
private Connection connection;
private PreparedStatement ps;
public XMLFeedParser() {
}
protected void initParser() throws SQLException {
connection = datasource.getConnection();
Statement deleteStatement = connection.createStatement();
deleteStatement.executeUpdate("DELETE FROM mytable WHERE id_feed = "+feed.getId());
deleteStatement.close();
ps = connection.prepareStatement(
"INSERT INTO mytable "
+ "(first, second, ...) "
+ "values (?, ?, ...)"
);
}
protected void finalizeParser() throws SQLException {
if (ps!=null) {
ps.executeBatch();
ps.close();
}
if (connection!=null) {
connection.close();
}
}
public void parseAndWriteToDatabase(String filePath) throws ParserConfigurationException, SAXException, IOException, SQLException {
File file = Paths.get(filePath).toFile();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
initParser();
saxParser.parse(file, this);
finalizeParser();
}
private void writeToDb(MyXMLFeedItem item) {
try {
ps.setString(1, "first");
ps.setString(2, "second");
// ...
ps.addBatch();
if (counter % STATEMENT_BATCH_THRESHOLD == 0) {
ps.executeBatch();
}
} catch (SQLException e) {
logger.severe(e.getMessage());
}
}
@Override
public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attrs) throws SAXException {
// ...parsing logic
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// ...parsing logic
}
@Override
public void endElement(String namespaceURI, String localName, String qualifiedName) throws SAXException {
// calls writeToDb() for each record found
}
}
我XMLFeedParser在我的EJB之一,它將調用parseAndWriteToDatabase()方法注入(使用@Inject)。有用!
疼痛從這裏開始。自解析結束以來,我的應用程序開始在其他點隨機發出錯誤。堆棧跟蹤看起來是這樣的:
Caused by: javax.resource.ResourceException: IJ000453: Unable to get managed connection for java:jboss/datasources/spazio_visione
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:646)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:552)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:737)
at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:138)
... 165 more
Caused by: javax.resource.ResourceException: IJ000655: No managed connections available within configured blocking timeout (30000 [ms])
at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.getConnection(SemaphoreArrayListManagedConnectionPool.java:553)
at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getSimpleConnection(AbstractPool.java:622)
at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getConnection(AbstractPool.java:594)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:579)
... 168 more
它看起來像我沒有關閉連接,但事實並非如此! 有什麼建議嗎?
其實,你的回答讓我以正確的方式! 我沒有檢查解析器中的異常,並且並不總是調用finalize。 您可以使用資源示例代碼嘗試豐富答案嗎? ty –
增加了嘗試資源的示例 – user140547