Java Hibernate Session.SaveOrUpdate方法在每个项目之前调用select-是否有方法批处理这些选择?

Java Hibernate Session.SaveOrUpdate方法在每个项目之前调用select-是否有方法批处理这些选择?,java,mysql,hibernate,batch-processing,Java,Mysql,Hibernate,Batch Processing,我正在使用java/hibernate/mysql。我正在创建要保存到数据库的对象列表。有些项目是新的,有些已经在数据库中(我不知道是哪一个)。出于这个原因,我使用session.SaveOrUpdate方法,它可以在必要时插入并在必要时更新 问题是,每次调用saveOrUpdate(myObject)时,我都会看到一个select调用,用于检查此记录是否已经存在,因此如果我在N个对象上循环,则有N个select查询。我有没有办法把这些选择集中在一起 这种行为对性能有显著影响吗 谢谢 我得到的日

我正在使用java/hibernate/mysql。我正在创建要保存到数据库的对象列表。有些项目是新的,有些已经在数据库中(我不知道是哪一个)。出于这个原因,我使用session.SaveOrUpdate方法,它可以在必要时插入并在必要时更新

问题是,每次调用saveOrUpdate(myObject)时,我都会看到一个select调用,用于检查此记录是否已经存在,因此如果我在N个对象上循环,则有N个select查询。我有没有办法把这些选择集中在一起

这种行为对性能有显著影响吗

谢谢

我得到的日志是:

Hibernate: select price0_.product_id as product1_3_0_, price0_.store_id as 
store2_3_0_, price0_.date_updated as date3_3_0_, price0_.price as price3_0_, 
price0_.quality as quality3_0_, price0_.update_source as update6_3_0_ 
from realworld.price price0_ where price0_.product_id=? and price0_.store_id=?

Hibernate: select price0_.product_id as product1_3_0_, price0_.store_id as 
store2_3_0_, price0_.date_updated as date3_3_0_, price0_.price as price3_0_, 
price0_.quality as quality3_0_, price0_.update_source as update6_3_0_ 
from realworld.price price0_ where price0_.product_id=? and price0_.store_id=?

Hibernate: insert into realworld.price 
(date_updated, price, quality, update_source, product_id, store_id) 
values (?, ?, ?, ?, ?, ?)  

Hibernate: insert into realworld.price 
(date_updated, price, quality, update_source, product_id, store_id) 
values (?, ?, ?, ?, ?, ?)
生成此命令的代码是:

for (Price price : prices){
        HibernateCurrentSession.currentSession().merge(price); 
        i++;
        if ( i % batchsize == 0 ) { 
            //flush a batch of inserts and release memory:
            HibernateCurrentSession.currentSession().flush();
            HibernateCurrentSession.currentSession().clear();
        }

}

首先,这些选择和其他选择都是在同一个事务中执行的,所以它们应该工作得很快。获取它们的原因可能是,对于现有条目,Hibernate可能希望首先检查version字段(通过将其当前值与数据库中已有的值进行比较),这将在更新之前发出select。有关saveOrUpdate行为的更多详细信息,请参见

我认为在这种情况下,没有办法控制或批处理这些选择。要实现更高效的运营,您可以做以下几点:

  • 您有一个实体实例列表,希望将其当前状态持久化到db,并且不知道/不关心哪些实体实例已经将状态持久化到db,哪些是新的实体实例
  • 在给定事务中,使用
    session.merge(obj)
  • 现在,您只需对每个实例进行必要的修改(即根据您的业务逻辑需要)。您不再需要对其调用任何persist/update方法来将modif持久化到数据库,这将在提交事务时自动发生

您能发布我们的映射文件吗?这可能是因为属性“”为true。默认情况下,它是false。如果这确实是错误的,并且您使用的是乐观锁定,则在更新之前不会执行select。检查,这解释了Hibernate中的乐观锁定以及更新是如何发生的

谢谢,我尝试过使用merge,但是我仍然看到相同的行为。关于版本字段,我没有定义版本列——据我所知,在这种情况下,Hibernate应该使用悲观锁定——这是正确的吗?是否可以在不首先执行select查询的情况下执行saveOrUpdate?您是否可以发布一组显示select的日志,并提及生成这些日志的代码?老实说,我在hibernate中也遇到过类似的问题,它在没有任何明显原因的情况下执行了大量SQL(特别是selects)。而且,一如既往,不要忘记,如果愿意,您可以通过Hibernate在SQL中执行自己的本机查询,并自动将结果打包到相应的beansfor(Price-Price:prices){HibernateCurrentSession.currentSession().merge(Price);i++;if(i%batchsize==0){//刷新一批插入并释放内存:HibernateCurrentSession.currentSession().flush();HibernateCurrentSession.currentSession().clear();}嗯,你在那里做的不太好。Hibernate会自行处理查询的批处理,只要这些查询在同一个事务中。通过强制刷新会话,你会要求Hibernate执行更多的操作,而不仅仅是提交事务,这会增加不必要的开销。只需打开一个事务,在其中获取所需的所有信息实体,以便附加它们,然后根据需要修改(通过setter/getter等),然后提交事务。Hibernate将根据需要对此进行批处理。我正在刷新以利用Hibernate.jdbc.batch_size属性。我尝试删除刷新,但仍然得到相同的行为。谢谢,我正在使用注释,因此没有映射文件。在任何情况下,我都没有指定更新前选择=true。就像我写的一样就我所知,我正在使用悲观锁定,因为我没有添加@version列-我是否可能在不知情的情况下使用乐观锁定?我不认为Hib。如果没有声明版本字段,则默认情况下有必要使用悲观锁定。我认为它不会执行任何锁定。无论如何,如果您有Hibernate生成的SQL输出后,很容易看出他是否执行了悲观主义锁定,因为它将反映在该SQL中,例如执行“选择…用于更新”或“选择…用于共享”(取决于您使用的数据库)。如果Hibernate实际上由于悲观主义锁定而执行了这些选择,请尝试禁用它: