Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPQL: Receiving a Collection in a Constructor Expression

I'm using JPQL and want to receive some normal parameters and a collection in a Constructor Expression to directly create the DTO-objects. But if the Collection is empty, I always get a error because he doesnt find the right constructor:

The DTO-Class looks the following:

public class DTO {
    private long id;
    private String name;
    private Collection<Child> children;

    public DTO (long id, String name, Collection<Child> children){
    this.id = id;
    this.name = name;
    this.children= children;
    }
}

The Child-Class:

public class Child {
    private String name;
    private int age;
}

And now the Constructor Expression looks the following:

return (List<DTO>) getEm().createQuery("SELECT DISTINCT NEW de.DTO(p.id, p.name, p.childs) 
                                          FROM Parent p").getResultList();

The current problem is, that in case the Collection p.childs is empty, it says that it doesnt find the right constructor, it needs (long, String, Child) instead of (long, String, Collection).

Do you have any kind of solution or is it simply not possible to use a Collection in Constructor Expression?

Oh and one more thing: If I easily create two constructors (..., Collection childs AND ..., Child childs) I get no results, but no error too... in my eyes not really satisfiyng :-/

like image 493
Florian Avatar asked May 13 '11 22:05

Florian


People also ask

Which is JPQL aggregate function?

JPQL supports the five aggregate functions of SQL: COUNT - returns a long value representing the number of elements. SUM - returns the sum of numeric values. AVG - returns the average of numeric values as a double value.

What are the features of JPQL?

JPQL FeaturesIt is a platform-independent query language. It is simple and robust. It can be used with any type of database such as MySQL, Oracle. JPQL queries can be declared statically into metadata or can also be dynamically built in code.

Can JPQL join operations?

We can also join multiple entities in a single JPQL query: @Test public void whenMultipleEntitiesAreListedWithJoin_ThenCreatesMultipleJoins() { TypedQuery<Phone> query = entityManager.

What is the difference between JPQL and SQL?

The main difference between SQL and JPQL is that SQL works with relational database tables, records and fields, whereas JPQL works with Java classes and objects. For example, a JPQL query can retrieve and return entity objects rather than just field values from database tables, as with SQL.


1 Answers

The JPA spec (Version 2.0, 2.1 and 2.2 at least) doesn't allow the use of collections as parameters in constructor expressions. Section 4.8 defines a constructor expression like this:

constructor_expression ::=
        NEW constructor_name ( constructor_item {, constructor_item}* )
constructor_item ::=
        single_valued_path_expression |
        scalar_expression |
        aggregate_expression |
        identification_variable

A single_valued_path_expression is what it sounds like - a property expression that points to a scalar of some sort (such as p.id), a scalar_expression is also an expression that points to scalar, an aggregate_expression is the application of a function like sum which reduces a multi-valued expression to a scalar one, and an identification_variable is a reference to the type you're querying over. None of which can be collection-valued.

So, if your JPA provider lets you use collection-valued parameter in a constructor expression, it's because it's going above and beyond the spec. Which is very nice of it, but not something you can necessarily rely on!

like image 116
Tom Anderson Avatar answered Sep 24 '22 06:09

Tom Anderson