2

我正在为 EJB3 项目设计一个 DAO 层,它们是无状态会话 bean。出于某种原因,部分 DAO 不会使用 JPA,它们直接使用 JDBC 访问数据库。

因此,我没有注入EntityManager,而是注入了一个Datasource,从中我可以获取Connection,创建Session等等......为了避免重复工作,我制作了一个POJO BaseClass,它从Datasource开始获取Connection并且在销毁之前关闭它。所有的 JDBC DAO 都扩展了它,所以它们不需要自己做这样的工作。BaseClass 看起来像这样:

public abstract class MemDBDAO {

    @Resource(mappedName = "java:MagicCardDS")
    private DataSource dataSource;
    protected Connection dbConnection;

    @PostConstruct
    protected void startUp() {
        try {
            dbConnection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();  
        }
    }

    @PreDestroy
    protected void shutDown() {
        try {
            dbConnection.close();
        } catch (SQLException e) {
            e.printStackTrace();  
        }
    }

}

例如,一个 JDBC DAO 如下所示:

@Stateless
public class SessionDAOBean extends MemDBDAO implements SessionDAO {


    @Override
    public void createSession(String sessionId, Integer userId) {
        try {
            PreparedStatement statement = dbConnection.prepareStatement(
                    "INSERT INTO session VALUES(?, ?, ?, ?)");
            statement.setString(1, sessionId);
            statement.setInt(2, userId);
            statement.setBoolean(3, false);
            statement.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();  
        }
    }
...

当我将它部署到 JBoss 6 应用程序服务器时,我收到以下错误消息:

20:51:12,546 INFO  [org.jboss.resource.connectionmanager.CachedConnectionManager] Closing a connection for you.  Please close them yourself: org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6@9bb04a: java.lang.Throwable: STACKTRACE
    at org.jboss.resource.connectionmanager.CachedConnectionManager.registerConnection(CachedConnectionManager.java:278) [:6.1.0.Final]
    at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:524) [:6.1.0.Final]
    at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:941) [:6.1.0.Final]
    at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) [:6.1.0.Final]
    at piapox.com.magiccard.server.dao.MemDBDAO.startUp(MemDBDAO.java:32) [:]
    at piapox.com.magiccard.server.dao.SessionDAOBean.startUp(SessionDAOBean.java:35) [:]
...

那么我应该如何设计 JDBC DAO 会话 bean?有什么好的模式吗?谢谢!

4

1 回答 1

2

JBoss 可能正在监视已建立的连接。似乎服务器正在尝试关闭连接,即使它已经关闭,这些消息也可以忽略。可能消息不会中断正常处理并且可以通过更改 jboss 配置文件来禁用。

回调方法@PostConstruct&@PreDestroy由容器处理。它的供应商特定于为每个方法调用创建和销毁无状态会话 bean 实例。与池化状态一样,bean 实例可能会长时间处于活动状态。

最好在方法本身中打开连接并在方法中退出之前关闭它createSessionfinally以防运行时出现异常。

您也可以参考 JBoss 报告的这个错误

于 2011-11-17T18:18:15.673 回答