Hibernate创建了很多线程并冻结

时间:2015-05-05 13:47:37

标签: java hibernate

我正在构建一个从日志文件中读取信息并将这些数据保存到数据库中的应用程序。该信息是一组包,其中一些用户已添加到包中,如下所示:

Package: (Total: 14, Used: 11)
    CSHC, 11/11
    CTQ8, 11/11
    CTQ8, 11/11

每次我从日志中读取一个包时,我都会调用将包保存到数据库中。问题是在保存第4个包之后,应用程序冻结了。使用Debug我发现hibernate正在为每个保存操作创建一个会话,而不是在每次保存后关闭它,我认为这是问题所在,但我不确定这是否是导致问题的原因。

boolean erasePack = false;
Package pack = new Package();
//System.out.println("Zerei? "+ petrelLicensesInUse);
while (i < reportContent.size()){
    phrase = reportContent.get(i);
    if(erasePack){
        pack = new Package();
        erasePack = false;
    }


    if(phrase.contains(Constants.licenseUsageIdentifier)){
        licenseUsage = true;
        licenseUser = false;
        licenseIssued = phrase.substring((phrase.indexOf(Constants.totalLicenseAvailableId) + 10),phrase.indexOf(Constants.endLicensesIssued));
        licenseUsed = phrase.substring((phrase.indexOf(Constants.totalLicenseUsedId) + 12),phrase.indexOf(Constants.endLicensesUsed));
        licenseIssuedNum = Integer.parseInt(licenseIssued);
        licenseUsedNum = Integer.parseInt(licenseUsed);
        licenseUsageList.add(phrase.replaceAll(";  Total of ", ", Used: ").replaceAll("Users of ", "")
                .replaceAll(" licenses issued", "").replaceAll(" licenses in use", "").replaceAll("Total of", "Total:")
                .replaceAll(" license in use", "").replaceAll(" license issued", "").replace("  ", " "));
        if(licenseUsedNum != 0){
            pack.setUsers(new ArrayList<PbrUser>());
        }
    }

    if(phrase.contains(Constants.licenseUserIdentifier)){
        licenseUsage = false;
        licenseUser = true;
        currPckg =  phrase.substring((phrase.indexOf(Constants.licenseUserIdentifier) + 1),phrase.indexOf(Constants.licenseUserIdentifier + " "));
        version = phrase.substring((phrase.indexOf(Constants.version) + 3),phrase.indexOf(Constants.endVersion));
        vendorDaemon = phrase.substring((phrase.lastIndexOf(' ') + 1));
        pack.setNamePackage(currPckg);
        pack.setVersion(version);
        pack.setVendorDaemon(vendorDaemon);
        pack.setNumberOfPackageLicenses(licenseIssuedNum);

        //PackageController.create(pack);
    }


    if(licenseUser && phrase.contains(Constants.userStartDateId)){
        //System.out.println(phrase.indexOf(Constants.userStartDateId));
        currDate = transformDate(phrase.substring((phrase.indexOf(Constants.userStartDateId)+Constants.userStartDateId.length()),phrase.length()));
        //System.out.println(phrase.substring(Constants.spaceUntilUser +1,phrase.length()).indexOf(" "));
        currName = phrase.substring(Constants.spaceUntilUser, (Constants.spaceUntilUser + phrase.substring(Constants.spaceUntilUser +1,phrase.length()).indexOf(" ")+1));
        PbrUser pbrUser = new PbrUser(currName);
        //PbrUserController.create(pbrUser);
        reportMetadataList.add(new ReportMetadata(currName, currPckg, currDate));
        if(licenseUsedNum != 0){
            //PbrUser pbrUser = new PbrUser(currName);
            pack.getUsers().add(pbrUser);
        }
        contSave++;
    }

    if(licenseUser && contSave == licenseUsedNum){
        PackageController.create(pack);
        contSave=0;
        erasePack = true;
    }

        i++;
}

广告代码:

static protected void insert(Object object) {
    Transaction tx = null;
    Session session = SessionFactoryUtil.getSessionFactory().getCurrentSession();
    try {
        tx = session.beginTransaction();
        session.saveOrUpdate(object);
        tx.commit();
    } catch (RuntimeException e) {
        if (tx != null && tx.isActive()) {
            try {
                // Second try catch as the rollback could fail as well
                tx.rollback();
            } catch (HibernateException e1) {
                logger.debug("Error rolling back transaction");
            }
            // throw again the first exception
            throw e;
        }
    }
}

Hibernate Session工厂:

public class SessionFactoryUtil {

    private static SessionFactory sessionFactory;
    private static ServiceRegistry serviceRegistry;

    /**
     * disable constructor to guaranty a single instance
     */
    private SessionFactoryUtil() {
    }

    public static SessionFactory createSessionFactory() {
          Configuration configuration = new Configuration();
          configuration.configure();
          serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
          sessionFactory = configuration.configure().buildSessionFactory(serviceRegistry);
          return sessionFactory;
        }

    public static SessionFactory getSessionFactory() {
        return createSessionFactory();
    }

  /**
   * Opens a session and will not bind it to a session context
   * @return the session
   */
    public Session openSession() {
        return sessionFactory.openSession();
    }

    /**
   * Returns a session from the session context. If there is no session in the context it opens a session,
   * stores it in the context and returns it.
     * This factory is intended to be used with a hibernate.cfg.xml
     * including the following property <property
     * name="current_session_context_class">thread</property> This would return
     * the current open session or if this does not exist, will create a new
     * session
     * 
     * @return the session
     */
    public Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

  /**
   * closes the session factory
   */
    public static void close(){
        if (sessionFactory != null)
            sessionFactory.close();
        sessionFactory = null;

    }
}

1 个答案:

答案 0 :(得分:0)

问题是您对SessionFactoryUtil.getSessionFactory()的调用不是单身人士。它每次都会创建一个新的Session对象。将该方法修改为真正的单例,以便它只在第一次调用时创建一个新实例。

在您的代码完成后,您仍然会遇到无法正确关闭该会话的问题,因此您必须在应用程序结束时调用session.close()

修改

要改变的第一件事是调用getSessionFactory()来返回相同的实例:

public static SessionFactory getSessionFactory() {
    //return createSessionFactory();
    return sessionFactory;
}

现在我们必须确保在调用sessionFactory之前创建getSessionFactory()。有很多方法可以做到这一点,其中一种更简单的方法是使用一个静态块,它将在类加载时被调用(第一次任何代码调用任何SessionFactoryUtil方法)

public class SessionFactoryUtil {

   ...fields declared the same 

   static{
         createSessionFactory();
   }

  ...
}

如果没有看到剩下的代码,我无法确定,但将createSessionFactory()设为私有可能是个好主意,因此没有其他人可以覆盖您的sessionFactory实例。