0

我有一个独立的线程应用程序。这是一个等待消息的侦听器,当它到达时做一些事情,我必须将消息保存在数据库中。但是我遇到了问题,因为如果我运行应用程序并“手动发送消息”一切正常,但是如果我运行应用程序并等待系统消息(例如,它到达后一小时),当 APP 运行时保存到它下沉的数据库,告诉:

java.sql.SQLException:Io 异常:连接重置或 java.sql.BatchUpdateException:Io 异常:连接重置

我正在使用带有 C3p0 0.9.2.1 的 Hibernate 3.2.6

会话的配置是:

public final class PersistenceUtil{
    private static final SessionFactory sessionFactory;

    static {
        try {
            String location = ServiceLocator.getInstance().getConfigurationService().getProperty("adaptor.location");
            if (LOC_1.equals(location)) {
                sessionFactory = new AnnotationConfiguration().configure("hibernate.1.cfg.xml").buildSessionFactory();
            } else if(LOC_2.equals(location)) {
                sessionFactory = new AnnotationConfiguration().configure("hibernate.2.cfg.xml").buildSessionFactory();
            }else {
                sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
            }
            sessionFactory.openSession();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }


    private PersistenceUtil() {
    }

    public static void shutdown() {
        try {
            sessionFactory.close();
        } catch (HibernateException e) {
            LOG.error("PersistanceUtil.shutdown Error: " + e.getMessage());
        }

    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

当我想保存时(错误在哪里):

public T save(T entity) {

        if (!getSession().getTransaction().isActive()) {
            log.warn("Session not active. Starting the session");
            getSession().beginTransaction();
        }

        getSession().save(entity);
        getSession().getTransaction().commit();
        return entity;
    }

而我的 hibernate.cfg.xml 是:

<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="connection.url">URL</property>
        <property name="connection.username">USER</property>
        <property name="connection.password">Password</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <!-- <property name="hibernate.hbm2ddl.auto">update</property> -->
        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <property name="hibernate.c3p0.min_size">1</property>
        <property name="hibernate.c3p0.max_size">100</property>
        <property name="hibernate.c3p0.timeout">3000</property>
        <property name="hibernate.c3p0.max_statements">0</property>
        <property name="hibernate.c3p0.idle_test_period">0</property>

        <mapping class="MessageEO" />
        <mapping class="CustomerEO" />

    </session-factory>
</hibernate-configuration>

我究竟做错了什么?提前致谢

4

1 回答 1

1

为什么在尝试保存数据之前不创建新会话?根据 Hibernate 的文档,这是原子操作的正确方法。正如我在代码中看到的您的评论,您认为启动事务意味着启动新会话或打开新连接,这不是真的。每个会话可以有多个(但不总是嵌套的)事务。我总是使用以下模板进行原子操作——它从不让我失望。我什至将这段代码作为 Eclipse 中的模板:

Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();
        // save/ update / delete your entities here
        tx.commit();
    } catch (RuntimeException ex) {
        if (tx != null) {
            tx.rollback();
        }
        throw ex;
    } finally {
        session.close();
    }

原则:

  1. 握住单个SessionFactory物体。创建它是昂贵的。
  2. 对于每一项操作(保存、修改等)或单个实体使用工厂打开新会话 - 它是轻量级和线程安全的。
  3. 会话本身不是线程安全的。
  4. 如果需要,请始终启动新事务并滚动提交/回滚它们。即使是只读数据获取。
  5. 完成批量操作(释放连接等)后始终关闭会话
  6. 永远不要在发生异常时使用相同的会话。
于 2013-11-05T08:17:11.620 回答