gpt4 book ai didi

java - @Resource数据源中断数据库连接

转载 作者:行者123 更新时间:2023-12-01 11:24:51 29 4
gpt4 key购买 nike

我最近在我的 Web 应用程序中编写了一个类,用于解析一个巨大的 XML 文件并向数据库表提供其内容。我的应用程序在 Wildfly9 上运行,并使用 JPA 和 Hibernate 提供程序来处理 MySQL 数据库。

AS 配置非常标准,我刚刚添加了我的数据源配置:

<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&amp;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 实体来管理我的域模型,一切始终运行良好。

回到我的解析器...实际上,由于多种原因,它需要使用 native 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 被注入(inject)(使用 @Inject)到我的一个 EJB 中,它将调用 parseAndWriteToDatabase() 方法。有用!

痛苦从这里开始。自解析结束以来,我的应用程序开始在其他点随机地给出错误。堆栈跟踪如下所示:

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

看起来我没有关闭连接,但事实并非如此!有什么建议吗?

最佳答案

有几种可能会出现问题。首先,您在 initParser() 中打开连接,但在 finalizeParser() 中关闭它,而不使用finally。如果抛出异常,则连接不会关闭。使用 try-with-resources 仍然会更好。

另一个潜在的问题是该类不是线程安全的。例如,如果在没有同步的情况下使用实例,如果您在 finalizeParser() 之前调用 XMLFeedParser.initParser() 两次,则可能会丢失对 connection 的引用 然后永远不会关闭(注入(inject) XMLFeedParser 的 EJB 是什么样子?)

编辑:使用 try-with-resources:这取决于您在哪里需要连接。您可以在 parseAndWriteToDatabase() 中打开连接并将其传递给您需要它的方法。因此您不必显式调用 close()。您的PreparedStatements 和ResultSets 也可以包装在try-with-resources 中。

例如:

 public void parseAndWriteToDatabase(String filePath) throws ParserConfigurationException, SAXException, IOException, SQLException {

// ...
try (Connection connection = getDataSource().getConnection();)
{
initParser(connection);
saxParser.parse(file, this);
finalizeParser(connection);
}
}

因此,当您的 Connection 和其他变量不是类的成员时,您不必担心其他线程访问它们。

关于java - @Resource数据源中断数据库连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30909977/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com