Question

I am developing a file management application under JSF/Primefaces and Tomee/OpenJPA. I am having a weird bug that is getting me crazy !

So here is my Entity :

   @Entity
        public class MyBoxFile implements Serializable {
            private static final long serialVersionUID = 1L;    

            @Id
            @GeneratedValue(strategy=GenerationType.AUTO)
            private int id;

            private String name;

            private String fileType;   

            @Lob
            @Basic(fetch=FetchType.LAZY, optional=true)
            @Column(nullable = true, length=2000000000)
            private byte[] file;    

            @OneToOne(fetch=FetchType.EAGER)
            private MyBoxUser owner;    

            @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
            @JoinColumn(name="PARENT_ID")
            private MyBoxFile parent;    

            @OneToMany(mappedBy="parent", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
            private List<MyBoxFile> childs = new LinkedList<>();

            //Getters & Setters ..
        }

It represent files and directories (depending on fileType). A directory could have children. I am creating the database from my entities. To retrieve all the directories of the database I use this code:

public List<MyBoxFile> findAllUsersDirs(MyBoxUser owner) {
    owner = em.find(MyBoxUser.class, owner.getLogin());
    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaQuery<MyBoxFile> criteriaQuery = criteriaBuilder.createQuery(MyBoxFile.class);
    Root<MyBoxFile> from = criteriaQuery.from(MyBoxFile.class);
    criteriaQuery.where(
        criteriaBuilder.and(
                       criteriaBuilder.equal(from.get(MyBoxFile_.owner), owner),

                     criteriaBuilder.equal(from.get(MyBoxFile_.fileType), "directory")
        )
    );

    TypedQuery<MyBoxFile> typedQuery = em.createQuery(criteriaQuery);
    return typedQuery.getResultList();
}

My problem is that whenever I exceed 1 child of a directory I get this error:

The bean encountered a non-application exception; nested exception is: <openjpa-2.3.0-nonfinal-1540826-r422266:1542644 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: null

And the error is at line return typedQuery.getResultList();

Persist and merge work just fine (I can persist a child of child, in the database it looks good, but with the criteriaQuery i get the error)

Does anyone see where could the problem come from ? Thanks (I am literally getting crazy ! I did my best to write the question correctly indented, sorry if not looking good)

Was it helpful?

Solution 2

At last I found the answer !! In fact, the collections annotated @OneToMany and @ManyToOne cause the framework to go into an infinite loop when trying to fetch a MyBoxFile with its parent and children (when fetching the parent it will try to fetch its children and then for each child try to fetch its children and its prents ... infinitely !). The most unexpected solution is to add the transient keyword for each one of these collections (it was only luck which got me to try it). I hope it will help someone in the future.

OTHER TIPS

Assuming that JPQL query would look like this:

SELECT mbf
FROM MyBoxFile mbf
WHERE mbf.fileType = 'directory' AND mbf.owner = :owner

then related criteria based query may look as follows:

public static List<MyBoxFile> findAllUsersDirs(MyBoxUser owner,String fileType) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<MyBoxFile> cq = cb.createQuery(MyBoxFile.class);
    Root<MyBoxFile> mbf = cq.from(MyBoxFile.class);

    cq.select(mbf);
    cq.where(cb.and(
        cb.equal(mbf.get(MyBoxFile_.owner), cb.parameter(MyBoxUser.class, "p1")),
        cb.equal(mbf.get(MyBoxFile_.fileType), cb.parameter(String.class, "p2"))
    ));

    TypedQuery<MyBoxFile> q = em.createQuery(cq);
    q.setParameter("p1", owner);
    q.setParameter("p2", fileType);
    return q.getResultList();
}

and finally the invocation:

List<MyBoxFile> result = findAllUsersDirs(owner, "directory");

I hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top