Eeko Eeko - 1 year ago 271
Java Question

Selecting nested Hibernate immutable objects throws org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: new


  • Hibernate 4.1.6

  • Spring 4.1

  • Java 8

I have two immutable data models:

Parent model

public class Parent {
private final String name;

@OneToMany(cascade=CascadeType.ALL, mappedBy="parent")
Map<String, Child> children = new HashMap<>(1);

public Parent(String name) { = name;

public putChild(Child c) {
Child childWithRef = new Child(this, c.getKey());
children.put(c.getKey(), childWithRef);

Child model

public class Child {
@JoinColumn(name="PARENT_ID") //say Parent has a generated ID
private final Parent parent;

private final String key;

public Child(Parent p, String key) {
this.parent = p;
this.key = key;

And I want to fetch all the children, with their parents, so I try running (
is from Spring):

entityManager.createQuery("SELECT new Child(new Parent('sample name'), c.key) FROM Child c").getResultList()

But I get an exception (the problem indicated is with the second

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: new near line 1, column ...

Does anyone know how to fetch nested immutable objects?

I know Hibernate is really against immutability. Since I'm only performing simple database tasks, I'd like to try nonetheless.

Answer Source

Your query is illegal for JPQL. The JPQL BNF (JPA 2.1 spec) states very clearly

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

You cannot nest constructor expressions.

Extract it out into a single object and then split into your structure in your code. For example

SELECT c.key FROM Child c

to get the "key" of the child, and then create the objects yourself in your code.


Here is the full solution in case someone needs it too (there are probably many ways to improve and add performance, so use this as base for understanding):

//fetch all fields without instantiating any models from Hibernate;
//all aliases are for understanding only;
//notice `INNER JOIN c.parent` for fetching the parent data
List<Object[]> results = entityManager.createQuery("SELECT as parentId, as parentName, p.key as parentKey, c.key as childKey FROM Child c INNER JOIN c.parent").getResultList()

//use map for parents identification
Map<Long, Parent> parentsMap = new HashMap<>(results.size())

//now use the data to instantiate the immutable models
results.forEach(resultRecord -> {
    Long parentId = (Long) resultRecord[0];
    if (parentsMap.get(parentId) == null) { //first time meeting this parent
        Parent p = new Parent(resultRecord[0], resultRecord[1], resultRecord[2]);
        parentsMap.put(parentId, p);

    Child c = new Child(parentsMap.get(parentId), resultRecord[3]);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download