Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 菜单树与冬眠在发挥!_Java_Hibernate_Jpa_Tree_Playframework - Fatal编程技术网

Java 菜单树与冬眠在发挥!

Java 菜单树与冬眠在发挥!,java,hibernate,jpa,tree,playframework,Java,Hibernate,Jpa,Tree,Playframework,我的第一个项目是Hibernate/JPA和Play!,我有一个菜单,一旦工作,将支持更改(即,轻松地将节点添加到树中)。挣扎(在>5小时的意义上)只是为了把基本的建模结合在一起: 模型: @Entity @Table(name = "Node") public class Node extends Model { @Column(nullable=false) public String description; @OneToMany(cascade=Cascade

我的第一个项目是Hibernate/JPA和Play!,我有一个菜单,一旦工作,将支持更改(即,轻松地将节点添加到树中)。挣扎(在>5小时的意义上)只是为了把基本的建模结合在一起:

模型:

@Entity
@Table(name = "Node")
public class Node extends Model {

    @Column(nullable=false)
    public String description;

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="parent")
    public List<Node> children = new LinkedList<Node>();

    @ManyToOne
    @JoinColumn(name="parent", insertable=false, updatable=false)
    public Node parent;

    public Node(){}

}
测试:

public class MenuTest extends UnitTest {

    private static final String TEST_MENU = "testMenu";

    @Test
    public void testMenu() {

        // test build/get

        Node root = NodeUtil.getRoot(TEST_MENU);
        assertNotNull(root);

        // delete all children - maybe from previous tests etc.
        for(Node o : root.children)
           o.delete();
        root.save();

        // test add

        root = NodeUtil.getRoot(TEST_MENU);

        NodeUtil.addChild(root, "child 1");
        NodeUtil.addChild(root, "child 2");
        NodeUtil.addChild(root, "child 3");

        assertEquals(3, root.children.size());
        assertEquals("child 3", root.children.get(2).description);

        assertEquals(0, root.children.get(1).children.size());

        Node node = root.children.get(1);
        NodeUtil.addChild(node, "subchild 1");
        NodeUtil.addChild(node, "subchild 2");
        NodeUtil.addChild(node, "subchild 3");
        NodeUtil.addChild(node, "subchild 4");

        NodeUtil.addChild(root.children.get(2), "sub subchild");

        assertEquals("sub subchild", root
                                    .children.get(1)
                                    .children.get(2)
                                    .children.get(0)
                                    .description);

        assertEquals(4, root.children.get(1).children.size());

        root.save();

        // test delete

        root = NodeUtil.getRoot(TEST_MENU); // regrab the root via hibernate, assuming there isnt it isnt cached this will get changes that have been persisted to the db (maybe?)

        root.children.get(1).children.get(2).delete();
        assertEquals(3, root.children.get(1).children.size());

        //root.delete();

    }

}
问题:

  • 我做错了什么?(也就是说,我无法对这个简单的想法进行建模并通过单元测试。正如我所说,Hibernate是新手,我所做的每一个更改都会产生一个新的Hibernate错误变量,这对我来说毫无意义。例如,当前的设置抛出“分离实体传递到persist:models.Node”)

  • 最初,我将整个util类作为模型类中的一组静态方法。首先,静态方法是否会影响Hibernates建模?如果是这样的话,简而言之,在什么情况下,我可以有静态方法(以及各位成员,来考虑它)对对象建模是“暂时的”

  • 假设我将util方法保存在一个单独的公共util类中,那么这个类通常存储在play框架中的什么位置?目前,它位于models包中Node.java旁边


  • 我不熟悉Play框架,但我可以提出一些关于使用Hibernate的观点:

    • 维护内存中对象的一致状态是您的责任。考虑下面的代码:

      for(Node o : root.children)
          o.delete();
      root.save();
      
      您指示Hibernate从数据库中删除子对象,但内存中的
      根对象仍然引用它们。由于关系配置为级联,Hibernate将再次尝试保存它们(我猜这是“分离实体传递到持久化”错误的原因)。所以,通过清除
      root.children
      来保持对象在内存中的状态一致

    • Hibernate在很大程度上依赖于。我不确定Play是如何管理它的,但看起来您应该在unittests中调用
      clearJPASession()
      ,以确保现有会话状态不会影响进一步的操作:

      root.save();
      
      clearJPASession();
      
      // test delete
      root = NodeUtil.getRoot(TEST_MENU);
      
    • 支持但不推荐您定义关系的方式(请参阅)。请改用以下方法:

       @OneToMany(mappedBy = "parent", cascade=CascadeType.ALL, fetch=FetchType.EAGER)                           
       public List<Node> children = new LinkedList<Node>();
      
       @ManyToOne
       @JoinColumn(name="parent")
       public Node parent;
      
      @OneToMany(mappedBy=“parent”,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
      public List children=new LinkedList();
      @许多酮
      @JoinColumn(name=“parent”)
      公共节点父节点;
      
    • 静态方法不会干扰Hibernate


    非常感谢!你确实让我走上了正确的道路。(1) 我已经同步了内存状态和休眠/db状态。(2) 我偷偷地在游戏的引擎盖下偷看了一眼!它看起来像大多数
    delete()
    save()
    调用
    EntityManager.flush()
    ,这听起来像您所说的
    clearJPSSession()
    。(3) 我已经改变了我的关系,尝试让它工作,现在只是单向的(默认设置,正如我在你发送的链接上看到的,这是推荐的joinTable方法)。但是仍然不起作用。(4)静态和非静态都是这样吗?也就是说,非静态成员函数会干扰,或者我可以在模型对象中自由使用它们吗?@davin:非静态方法也不会干扰Hibernate,除非它们被命名为getter或setter。另外,
    flush()
    可能还不够,因为它不会清除会话缓存,因此进一步尝试加载对象将导致相同的实例。再次感谢。我接受了你的回答,因为它帮助我解决了很多问题。
     @OneToMany(mappedBy = "parent", cascade=CascadeType.ALL, fetch=FetchType.EAGER)                           
     public List<Node> children = new LinkedList<Node>();
    
     @ManyToOne
     @JoinColumn(name="parent")
     public Node parent;