0

我正在尝试在两个 while 循环中插入许多行。我的理解是我必须在事务的循环体中创建一个单独的新瞬态实例。

根据我的经验,不创建单独的瞬态实例(循环体外部的瞬态实例)至少插入一行,即最后一行。在提交交易之前我save只需要在这里使用一次吗?

在这种情况下使用flush()和正确吗?clear()

我对hibernate比较陌生。我会感谢任何帮助或指出我正确的方向。

请原谅我蔑视变量和方法的骆驼案例约定。

public boolean addVariableHonorariumDetails(Monthly_variable_honorarium_processing mvhp
                                             , Monthly_variable_group_honorarium_processing mvghp
                                             , Monthlyvariablecompid compositeID)
{
    Session session = HibernateUtil.getSessionFactory().openSession();   
    Transaction tx = null;
    String ccyymm = mvhp.getMvhp().getVariable_monthly_ccyy()+mvhp.getMvhp().getVariable_monthly_month();

    try
    {
        tx = session.beginTransaction();

        // ctrl query

        M_control_table mct = (M_control_table) session.createQuery("from M_control_table").uniqueResult(); //single result

        Query query = session.createSQLQuery(
"Select c.Booklet_type, SUM(c.End_Leaf -  c.Start_Leaf +1) as No_of_Coupons from m_coupon_sale c where date_format(c.Booklet_Sale_Date, '%Y%m') = :string and c.Booklet_type in ('GR','PI') group by c.Booklet_Type")
                             .addScalar("c.Booklet_type", Hibernate.STRING)
                             .addScalar("No_of_Coupons", Hibernate.STRING)
                             .setString("string", ccyymm);

        ScrollableResults results = query.scroll();

        Integer sumTotalOfPayment = 0;
        while ( results.next() )
        {
            Object[] row = results.get();

            mvghp.setMvhpgroup(new Monthlyvariablecompid(mvhp.getMvhp().getVariable_monthly_month()
                              , mvhp.getMvhp().getVariable_monthly_ccyy()
                              , row[0].toString())
                              );

            mvghp.setNo_of_items(row[1].toString());

            Integer no_of_items = Integer.parseInt(mvghp.getNo_of_items(), 10);

            mvghp.setGroup_rate( (row[0].toString().equals("GR")) ? mct.getRate_for_green_coupons()
                                                                  : mct.getRate_for_pink_coupons()  );

            Integer variable_payment = no_of_items * Integer.parseInt( mvghp.getGroup_rate(), 10);
            sumTotalOfPayment = sumTotalOfPayment + variable_payment;

            mvghp.setVariable_payment(variable_payment.toString());

            session.save(mvghp);
            session.flush();
            session.clear();
        }

        Query query2 = session.createSQLQuery(
"select m.pooja_name, count(*) as no_of_items from t_pooja_booking t inner join m_pooja_detail m on t.pooja_id=m.pooja_id where date_format(t.pooja_date, '%Y%m')= :string and m.pooja_name in ('A','B' ) group by m.pooja_name")
                                             .addScalar("m.pooja_name", Hibernate.STRING)
                                             .addScalar("no_of_items", Hibernate.STRING)
                                             .setString("string", ccyymm);

        ScrollableResults results1 = query2.scroll();

        while ( results1.next() )
        {
            Object[] row = results1.get();

            mvghp.setMvhpgroup(new Monthlyvariablecompid(mvhp.getMvhp().getVariable_monthly_month()
                                , mvhp.getMvhp().getVariable_monthly_ccyy()
                              , row[0].toString())
                              );

            mvghp.setNo_of_items(row[1].toString());
            Integer no_of_items = Integer.parseInt(mvghp.getNo_of_items(), 10);

            mvghp.setGroup_rate((row[0].toString().equals("A"))?mct.getRate_for_108_vadamalas_cook()
                                                                             :mct.getRate_for_51_vadamalas_cook() );

            Integer variable_payment = no_of_items * Integer.parseInt(mvghp.getGroup_rate() , 10) ;
            sumTotalOfPayment = sumTotalOfPayment + variable_payment;

            mvghp.setVariable_payment(variable_payment.toString());

            session.save(mvghp);
            session.flush();
            session.clear();
        }


        mvhp.setTotal_variable_payment(sumTotalOfPayment.toString());
        session.save(mvhp);

        tx.commit();

    }
    catch(Exception e)
    {
        if(tx!=null)
        {
            tx.rollback();
        }
        e.printStackTrace();
        return false;
    }
    finally
    {
        session.close();
    }

    return true;
}
4

1 回答 1

1

为循环中的每次迭代调用 session.save(mvghp)、session.flush() 和 session.clear() 充其量是低效的,并且似乎它可能是您的困惑的一部分。

让我们回到基础。在 Hibernate 中,每个对象松散地表示顶级表中的一行,以及连接到该顶级行的子表中的行。(是的,也有例外,是的,这过于简单化了,但对于刚接触 Hibernate 的人来说,这是一个很好的工作模型,可以帮助您站稳脚跟。)这意味着,如果您最终要获得多个最后表中的行(例如,每次循环迭代一次),您应该以多个对象结束,每行一个。你在做什么(重用同一个 Hibernate 对象)违背了这一点;如果我正确理解了您的用例,您应该为循环中的每次迭代创建一个新的 Hibernate POJO(Plain Old Java Object 的缩写)。

其次,POJO 可以是持久的(您的 Hibernate 会话知道该对象,并将在您的事务被刷新或关闭时保存对数据库的更改)或瞬态的(Hibernate 不知道该对象的任何信息,并且不会保存更改数据库)。调用 save() 使瞬态对象持久化(并且对已经持久化的 POJO 没有影响!);它可能是 Hibernate API 中命名最差的方法,应该调用 makePersistent() 而不是 save(),因为它实际上并没有将对象保存到数据库中。相反,它使它持久化,因此它最终会保存到数据库中。对 clear() 的调用则相反:它获取会话中的所有持久对象并使它们成为非持久对象,丢弃进程中的所有更改,并且它对已经是瞬态的 POJO 没有影响。

而 flush() 只是强制 Hibernate 将所有对持久对象的更改写入数据库;如果 Hibernate 愿意,它可以在任何其他时间自由地执行此操作,并且保证在会话的事务提交时执行此操作,但调用 flush() 会强制它立即执行此操作。但它不会提交事务,因此 a) 如果事务回滚,您仍然会丢失这些更改,并且 b) 如果您正在查看,则在事务提交之前,您不会看到数据库中的更改SQLPlus 之类的东西。它通常仅在您希望在运行基于 SQL 的查询之前将您的更改从 POJO 推送到数据库时有用,您希望它考虑您刚刚所做的更改,

因此,当您为每个 POJO 调用 save()、flush() 和 clear() 时,您所做的是使该对象持久化,然后强制数据库将其数据写入 DB,然后使其短暂的。然后在下一次循环迭代期间对其数据进行更改,当您再次使其持久化时,Hibernate 认为它是一个新对象(如您所愿)并将新行保存到数据库中。这是可行的,但是所有的刷新都是低效的(并且让熟悉 Hibernate 的人感到困惑),并且您只需创建 POJO 类型的 N 个实例并在每个实例上调用 save() 即可获得相同的行为(没有 flush(), no clear()),具有更好的性能和更少的混乱。

此外, clear() 有点像大锤。它删除了所有您的 Hibernate 会话中的 POJO,这可能会导致任何期望能够更改这些对象并使这些更改保持不变的代码出现非常意外的行为。(您之前对 flush() 的调用将确保已经进行的任何更改都被持久化,但不会做任何事情来确保将来的更改会发生。)这也意味着任何时候 Hibernate 需要检索这些对象中的任何一个,它都有一直回到数据库而不是从会话的缓存中提取它们,这是低效的。如果你真的想使用你在这里得到的方法(我偶尔会这样做,例如在我想结束许多对象但无法合理地为每个对象构造一个新对象的情况下,所以我重用同一个对象,同时改变它的属性 s 瞬态并且不跟踪这些更改,然后短暂使其持久化,因此它将“新”对象写入数据库),您可能想要使用的方法是 evict() 方法,它允许您仅删除一个从缓存中休眠对象。但我想强调的是,即使 evict() 更多的是专家专用功能,在大多数情况下,您都不需要它(也不应该使用它),包括您的示例中的那些。

希望这可以帮助您进一步了解 Hibernate...

于 2013-07-24T06:14:36.867 回答