Ebean部分不保存ManyToOne关联

时间:2014-10-29 10:04:54

标签: java database playframework-2.0 ebean

PREAMBLE

我正在努力解决一个非常奇怪的问题。 我正在尝试创建一个" Web应用程序boostrap"过程 - 运行应用程序,填写初始数据库,执行一些增强功能,并准备好提供服务。

我有一张40000多个Stuff记录表。 我有一张包含10000多条教学记录的表格。

每个东西物品都有一条指令。 - > Stuff-Instruction是ManyToOne的关系。

我的应用程序启动的步骤是:

  1. 填写Stuff项目,但不要初始化他们的指令。
  2. 填写所有说明
  3. 尝试将内容与说明相关联
  4. 现在我如何执行第3步:

    public class AssociateJob {
    
    //TODO - !! there are some gaps in processing! Why??
    private static final int PAGE_SIZE = 100;
    
    /**
     * Best effort to associate stuff and instructions
     *
     * @return count of orphaned (instruction == null) stuffs
     */
    public int associate() {
        PagingList<Stuff> stuffs = Stuff.find.findPagingList(PAGE_SIZE);
        return processPagingList(stuffs);
    }
    
    
    
    private int processPagingList(PagingList<Stuff> pages) {
        int countNull = 0;
        for (int page = 0; page < pages.getTotalPageCount(); page++) {
            Page<Stuff> stuffsPage = pages.getPage(page);
            countNull += processPage(stuffsPage);
        }
        return countNull;
    }
    
    private int processPage(Page<Stuff> stuffsPage) {
        List<Stuff> list = stuffsPage.getList();
        return processList(list);
    
    }
    
    private int processList(List<Stuff> list) {
        int countNull = 0;
        EbeanServer server = Ebean.getServer(null);
    
        Transaction tx = beginTransaction();
        Set<String> fields = new HashSet<>();
        fields.add("instruction");
    
        for (Stuff d : list) {
            Instruction i = Instruction.byNameAndForm(d.name, d.form);
            if (i == null) {
                countNull++;
                continue;
            }
            d.instruction = i;
            server.update(d, fields, tx);
    
        }
        commit(tx);
        return countNull;
    }
    
    
    private Transaction beginTransaction() {
        EbeanServer server = Ebean.getServer(null);
    
        Transaction transaction = server.beginTransaction();
        transaction.setBatchSize(100);
        transaction.setPersistCascade(false);
        return transaction;
    
    }
    
    private void commit(Transaction transaction) {
        transaction.commit();
    }
    

    }

    第3步完成后,AssociateJob.associate()方法会返回6 - 6个没有指令的东西,因此我必须稍后手动指定它。 / p>

    问题

    事实上,有许多未保存的关联。 当我执行:

    int countNull = Stuff.find.where().eq("instruction", null).findRowCount();
    

    我收到超过12 000个的东西,没有说明。

    问题

    为什么会这样?我该如何解决?

    目前我正在坚持一个时间紧张的解决方法(创建另一个工作来将事物与stuff.instruction == null相关联),但这非常糟糕,这可能是Ebean问题将影响我未来的内部处理。

1 个答案:

答案 0 :(得分:0)

感谢Rob's hint here,我找到了一个非常简单而优雅的问题解决方案:

public class AssociateJob {


    public int associate() {

        String sql = 
           "UPDATE stuff AS s SET instruction_id = " + 
           "(SELECT i.id FROM instruction AS i WHERE " + 
           "i.name LIKE s.name AND i.form LIKE s.form )" +
           " WHERE instruction_id IS NULL";

        SqlUpdate update = Ebean.createSqlUpdate(sql);

        return update.execute();

    }


}

所以整个批处理可以通过一个大的更新操作来完成,我没想到的方式,被ORM的面向对象方法的优雅所蒙蔽。