Serguey Asael Shinder: Hibernate 7.4.12: a lambda TupleTransformer no longer needs a matching constructor
Hibernate ORM 7.4.12.Final was published in the early hours of 4 October. The release notes only link to the issue tracker, and the comparison with 7.4.11 shows two fixes. One of them is worth knowing about if you map query results by hand.
The regression. HHH-20440, reported in May, describes a query like this failing:
Query<EmployeeWrapper> query = session
.createQuery("select empId, empName from Employee", EmployeeWrapper.class)
.setTupleTransformer((tuple, aliases) -> {
EmployeeWrapper w = new EmployeeWrapper();
w.setEmpId((Long) tuple[0]);
w.setEmpName((String) tuple[1]);
return w;
});
query.uniqueResult();

It threw InstantiationException: Cannot instantiate query result type, found no matching constructor. When the query plan was built, Hibernate looked for a constructor of EmployeeWrapper whose parameters matched the two selected columns, and gave up if there was none, even though the transformer was going to build the object itself and the constructor would never be called. The reporter traced it to an earlier commit; before it, an inline transformer like the one above worked.
The fix. In ConcreteSqmSelectQueryPlan, the constructor-based row transformer is still computed up front, but an InstantiationException there is now caught and the transformer left empty. When the query runs with a TupleTransformer set, that transformer is used; the constructor lookup only matters when there is no transformer. The fix adds a test with exactly the query above, asserting that uniqueResult() does not throw.
The second fix is for Quarkus users. HHH-20951: when one Quarkus Data entity (formerly Panache 2) extends another, Hibernate Processor generated static repository accessors such as managedBlocking() on both metamodels, with entity-specific return types that are not covariant, so the generated code did not compile. The processor now skips the default accessors on any metamodel whose entity has a Quarkus Data entity anywhere up its superclass chain. Accessors you name yourself in nested repositories remain.
Who should upgrade. Anyone on 7.4 who calls setTupleTransformer with a result class that has no constructor matching the select list, and anyone on Quarkus Data with entity inheritance and annotation processing turned on. If you worked around the first bug by adding a matching constructor, it can stay; it is simply no longer required.
No JDK runs on the machine this note was written on; the behaviour described is the one stated in the linked issues, the diff and its test.