JPA树价值传播/合并

JPA树价值传播/合并

问题描述:

JPA树价值传播/合并

@Entity 
public class Node 
{ 
    @ManyToOne 
    private Node parent; 

    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) 
    private List<Node> children; 

    @ManyToMany 
    private List<Owner> ownerList; 

    ... 
} 

,我想owner小号传播到孩子们在坚持/合并。规则是:

Any node must have at least its parent node owners 

我试图

@PreUpdate 
public void propagateOwnersTopDown(Node node) 
{ 
    for(Node child : node.getChildren()) 
    { 
     for(Owner owner : node.getOwnerList()) 
     { 
      if(!child.getOwnerList().contains(owner)) 
      { 
       child.getOwnerList().add(owner); 
      } 
     } 
    } 
} 

,要么

@PreUpdate 
public void propagateOwnersBottomUp(Node node) 
{ 
    if(node.getParent() == null) return; 

    for(Owner owner : node.getParent().getOwnerList()) 
    { 
     if(!node.getOwnerList().contains(owner)) 
     { 
      node.getOwnerList().add(owner); 
     } 
    } 
} 

即使我知道这是不合法的,而事实上,这些不工作(​​调用只在根上)。

我知道可以

  • 写信addOwner()方法,其传播所有者儿童
    • 但如果一些其他的代码调用node.getOwnerList().add(owner)传播被捣毁

  • 显式调用propagateOwnersTopDown()或类似之前em.merge(node)(通常在一个事务中)
    • 但我必须把它添加到每一个EJB /交易方法

我不知道是否有一些巧妙的方式来完成这一点。

我不是数据库专家,但它可以实现与存储过程/触发器/任何东西的一致性?

如果为true,是否可以/合法地调用程序/触发器/ @PrePersist/​​中的任何内容?

我在EclipseLink 2.5.2和MySQL 5.6上

谢谢。

+1

的EclipseLink 2.5.2具有JPA 2.1。 – Tiny 2014-09-27 10:56:57

+0

你说得对。谢谢。 – 2014-09-27 10:57:43

我实现我自己的监听器子系统:

protected <T extends AbstractEntity> void invokeListeners(T entity, Class<? extends Annotation> annotation) 
{ 
    ServiceListeners serviceListeners = entity.getClass().getAnnotation(ServiceListeners.class); 
    if(serviceListeners != null) 
    { 
     try 
     { 
      for(Class<?> listenerClass : serviceListeners.value()) 
      { 
       Object instance = listenerClass.newInstance(); 

       Set<Method> methods = ReflectionUtils.getAllMethods(listenerClass, ReflectionUtils.withAnnotation(annotation)); 
       for(Method m : methods) 
       { 
        m.invoke(instance, entity); 
       } 
      } 
     } 
     catch(Exception e) 
     { 
      throw new RuntimeException(e.getMessage(), e); 
     } 
    } 
} 

public <T extends AbstractEntity> void create(T entity) 
{ 
    invokeListeners(entity, OnCreate.class); 

    em.persist(entity); 
} 

public <T extends AbstractEntity> T update(T entity) 
{ 
    invokeListeners(entity, OnUpdate.class); 

    T entity2 = em.merge(entity); 
    em.flush(); 
    em.refresh(entity2); 

    return entity2; 
}