OpenJPA 1.2.x выбрать древовидную структуру с использованием JPQL - PullRequest
0 голосов
/ 06 ноября 2010

Я использую OpenJPA 1.2.x (JPA1). Проблема в том, что я не могу продолжить работу с древовидной структурой с использованием JPQL.

Пожалуйста, посмотрите мое лицо:

@NamedQueries(
         { 
           @NamedQuery(
             name="Department.getFullTree",
             query="SELECT dep FROM Department dep LEFT JOIN fetch dep.children"
           )
         }
        )
@Entity
public class Department {

    public static final Long ROOT_ID = 0L;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DEPARTMENT_SEQ")
    @SequenceGenerator(name="DEPARTMENT_SEQ", sequenceName="DEPARTMENT_SEQ", allocationSize=1)
    @Column(name="ID")
    private Long id;

    @Column(name="PARENT_ID")
    private Long parentId;

    @ManyToOne(targetEntity = Department.class, fetch = FetchType.EAGER)
    @JoinColumn(name = "PARENT_ID")
    private Department parent;

    @Column(name="LABEL")
    private String label;

    @OneToMany(mappedBy = "parent", 
               targetEntity = Department.class, 
               fetch=FetchType.LAZY, 
               cascade = {CascadeType.PERSIST, CascadeType.ALL})
    private List<Department> children;

И мой метод bean без состояния:

public Department getFullTree(){
    em.createNamedQuery("Department.getFullTree").getResultList();
    Department root = em.find(Department.class, Department.ROOT_ID); 
    return root;
}

Моя цель - получить полное дерево отделов, начиная с root. Я попробовал этот подход:

Это правда? Я использую DB2. И будет использовать его в будущем. JPA-запрос для получения всего дерева

Кажется, это не работает: http://www.tikalk.com/java/load-a-tree-with-jpa-and-hibernate

Я пытался повторить, но я получаю ошибку переполнения стека при обходе дерева (не более 200 узлов). Вывод отладки показал, что root является дочерним, поэтому это структура с круглыми связями ...

Что мне еще попробовать?

UPD: Вот мой код прохождения:

public class TreeTagHelper {

    private static final Logger LOG = LoggerFactory.getLogger(TreeTagHelper.class);

    private Department root;
    private JspWriter out;

    public TreeTagHelper(Department root, JspWriter out){
        LOG.trace("#init");
        this.root = root;
        this.out = out;
    }

    public void printTree() throws Exception{
        LOG.trace("#printTree -> start");
        out.println("<ul id=\"tree-root\"> ");      
        for(Department dep : root.getChildren()){
            printNode(dep, out);
        }       
        closeUL(out);
        LOG.trace("#printTree -> end");
    }

    public static void printNode(Department dep, JspWriter out) throws Exception{
        LOG.trace("#printNode title[{}] children.size()[{}]",dep.getLabel(), (dep.getChildren() == null ? "NULL" : dep.getChildren().size()) );
        openLI(out);
        out.print("<span id=\"tree_node_"+dep.getId()+"\" class=\"ekp-tree-node\" onclick=\"ekpCommon.tree.toggleBullet(this)\">"+dep.getLabel()+"</span>");
        if(dep.getChildren()!=null){
            openUL(out);
            for(Department child : dep.getChildren()){
                printNode(child, out);
            }
            closeUL(out);
        }

        closeLI(out);
    }

    public static void openUL(JspWriter  out) throws Exception{
        out.println("<ul>");
    }

    public static void closeUL(JspWriter out) throws Exception{
        out.println("</ul>");       
    }

    public static void openLI(JspWriter out) throws Exception{
        out.println("<li>");
    }

    public static void closeLI(JspWriter out) throws Exception{
        out.println("</li>");       
    }

LOG.trace ("# printNode title [{}] children.size () [{}]", dep.getLabel (), (dep.getChildren () == null? "NULL": dep.getChildren ( ) .size ()));

всегда выводит: "# printNode title [Все отделы] children.size () [19]" Похоже, корень («Все отделы») имеет 19 детей. Это правда, я проверил это в своей БД. Но у каждого ребенка есть корень! Так что это бесконечная структура ... ??? Рут детей не заводит? Сам выбирает?

Ответы [ 3 ]

1 голос
/ 06 ноября 2010

Я пытался повторить, но я получаю ошибку переполнения стека при обходе дерева (не более 200 узлов).Вывод отладки показал, что root является дочерним, поэтому он имеет структуру с круглыми связями ...

Тогда ваши данные, скорее всего, неверны.Дважды проверьте, что корень не имеет родителя.

0 голосов
/ 06 ноября 2010

Пожалуйста, смотрите мою структуру БД:

ID    PARENT_ID    LABEL
0     0        All Departments
1000   0           Central office

Вот почему JPA не работал: (

см. Первый ряд. Это корень дерева. Похоже, что JPA читает его как дочерний элемент, ссылающийся на себя (PARENT_ID существует в таблице, поэтому можно выполнить JOIN).

Я изменил значения БД:

ID    PARENT_ID    LABEL
0     -1           All Departments
1000   0           Central office

Теперь это работает! Да уж! :)

0 голосов
/ 06 ноября 2010

Я думаю, что вы делаете правильно и должны работать. Вы загружаете полную древовидную структуру в контекст постоянства, а затем получаете ссылку на корневой узел. Возможно, что-то не так с вашим деревом? Это будет единственное, что может вызвать StackOverflowError. Не могли бы вы опубликовать свой код?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...