在play framework 1.2.x, class JPABase分析中,为啥要调用saveAndCascade()?

Posted

技术标签:

【中文标题】在play framework 1.2.x, class JPABase分析中,为啥要调用saveAndCascade()?【英文标题】:in play framework 1.2.x , class JPABase analysis , why does it use the call saveAndCascade()?在play framework 1.2.x, class JPABase分析中,为什么要调用saveAndCascade()? 【发布时间】:2013-10-28 13:54:01 【问题描述】:
 public void _save() 
        if (!em().contains(this)) 
            em().persist(this);
            PlayPlugin.postEvent("JPASupport.objectPersisted", this);
        
        avoidCascadeSaveLoops.set(new ArrayList<JPABase>());
        try 
            saveAndCascade(true);
         finally 
            avoidCascadeSaveLoops.get().clear();
        
        try 
            em().flush();
         catch (PersistenceException e) 
            if (e.getCause() instanceof GenericJDBCException) 
                throw new PersistenceException(((GenericJDBCException) e.getCause()).getSQL());
             else 
                throw e;
            
        
        avoidCascadeSaveLoops.set(new ArrayList<JPABase>());
        try 
            saveAndCascade(false);
         finally 
            avoidCascadeSaveLoops.get().clear();
        
    


private void saveAndCascade(boolean willBeSaved) 
    this.willBeSaved = willBeSaved;
    if (avoidCascadeSaveLoops.get().contains(this)) 
        return;
     else 
        avoidCascadeSaveLoops.get().add(this);
        if (willBeSaved) 
            PlayPlugin.postEvent("JPASupport.objectUpdated", this);
        
    
    // Cascade save
    try 
        Set<Field> fields = new HashSet<Field>();
        Class clazz = this.getClass();
        while (!clazz.equals(JPABase.class)) 
            Collections.addAll(fields, clazz.getDeclaredFields());
            clazz = clazz.getSuperclass();
        
        for (Field field : fields) 
            field.setAccessible(true);
            if (Modifier.isTransient(field.getModifiers())) 
                continue;
            
            boolean doCascade = false;
            if (field.isAnnotationPresent(OneToOne.class)) 
                doCascade = cascadeAll(field.getAnnotation(OneToOne.class).cascade());
            
            if (field.isAnnotationPresent(OneToMany.class)) 
                doCascade = cascadeAll(field.getAnnotation(OneToMany.class).cascade());
            
            if (field.isAnnotationPresent(ManyToOne.class)) 
                doCascade = cascadeAll(field.getAnnotation(ManyToOne.class).cascade());
            
            if (field.isAnnotationPresent(ManyToMany.class)) 
                doCascade = cascadeAll(field.getAnnotation(ManyToMany.class).cascade());
            
            if (doCascade) 
                Object value = field.get(this);
                if (value == null) 
                    continue;
                
                if (value instanceof PersistentMap) 
                    if (((PersistentMap) value).wasInitialized()) 
                        for (Object o : ((Map) value).values()) 
                            if (o instanceof JPABase) 
                                ((JPABase) o).saveAndCascade(willBeSaved);
                            
                        
                    
                    continue;
                
                if (value instanceof PersistentCollection) 
                    if (((PersistentCollection) value).wasInitialized()) 
                        for (Object o : (Collection) value) 
                            if (o instanceof JPABase) 
                                ((JPABase) o).saveAndCascade(willBeSaved);
                            
                        
                    
                    continue;
                
                if (value instanceof HibernateProxy && value instanceof JPABase) 
                    if (!((HibernateProxy) value).getHibernateLazyInitializer().isUninitialized()) 
                        ((JPABase) ((HibernateProxy) value).getHibernateLazyInitializer().getImplementation()).saveAndCascade(willBeSaved);
                    
                    continue;
                
                if (value instanceof JPABase) 
                    ((JPABase) value).saveAndCascade(willBeSaved);
                    continue;
                
            
        
     catch (Exception e) 
        throw new UnexpectedException("During cascading save()", e);
    

为什么它使用调用 saveAndCascade()? 我查看了源代码,但我无法理解。 任何帮助表示赞赏。

我想学习playframework的使用方法,但是看不懂。我看了Play+Framework+Cookbook和Wayne Ellis - Introducing the Play Framework,但是找不到关于play源码的分析。 任何书籍、文档或声明都将受到赞赏。

【问题讨论】:

【参考方案1】:

在正常的 JPA 环境中,EntityManager.flush() 方法将检查所有加载的实体,如果它们被修改 - 更改将保存回数据库。

Play-1 的工作方式不同 - 此函数设置 willBeSaved 变量,稍后 Hibernate 拦截器会检查它并仅允许更新此特定实体,因此如果有其他修改过的实体 - 它们不会更新。

【讨论】:

以上是关于在play framework 1.2.x, class JPABase分析中,为啥要调用saveAndCascade()?的主要内容,如果未能解决你的问题,请参考以下文章

如何将参数传递给 Play 中的 Jobs!框架 1.2.x?

Play Framework:如何不查看文件夹以了解 Play Framework 中的更改

Play Framework 路由中的变量

在 Play framework 2.3 中设置 cookie sameSite

Play Framework - 是不是可以在 Play 中结合使用 Promise 和 WebSocket?

Play Framework 2.4.1:在测试模式下忽略 play.application.loader 设置