Previously EntityManagerFactory was created manually which resulted in LocalContainerEntityManagerFactoryBean not being exposed to
ApplicationContext. The latter is an important bean since it enables
exception translation.
Original pull request: #180.
We now create the count query that's required for pagination queries without applying the query hints.
Related tickets: DATAJPA-684
Original pull request: #182.
If a query returns a one-element tuple and that single element returned is type-compatible to the type to be returned we return it as is. Previously, we insisted on creating a Map from the tuple (which usually works for projection interfaces).
This is needed to support custom simple types (i.e. types that the JPA provider can convert itself but which are not exposed through the metamodel - usually types managed through JPA AttributeConverters or provider specific conversion mechanisms).
When creating the selections for a derived query using a projection we now explicitly create joins for plural attributes. Looks like Hibernate fails to create a proper query if the path is referred to via root.get(…) and the select clause includes references to other non-plural attributes.
We now decline sort expressions that contain functions such as ORDER BY LENGTH(name) when used with repository having a String query defined via the @Query annotation.
Think of a query method as follows:
@Query("select p from Person p where LOWER(p.lastname) = LOWER(:lastname)")
List<Person> findByLastname(@Param("lastname") String lastname, Sort sort);
Calls to findByLastname("lannister", new Sort("LENGTH(firstname)")) from now on throw an Exception indicating function calls are not allowed within the _ORDER BY_ clause. However you still can use JpaSort.unsafe("LENGTH(firstname)") to restore the behavior.
Kudos to Niklas Särökaari, Joona Immonen, Arto Santala, Antti Virtanen, Michael Holopainen and Antti Ahola who brought this to our attention.
We're now more lenient against manually defined queries that do not contain aliases when adding order by clauses to them. The alias detection now doesn't accidentally pick up "where" anymore in case no primary alias is declared and the code applying the order by clause only qualifies the expressions created if there actually is an alias in the first place.
We now exclude all candidates beans that could theoretically become an EntityManagerFactory unless we definitely know so.
Previously bean definitions for JndiObjectFactoryBean that didn't expose an expected type (e.g. ones defined via JavaConfig) were propagated to the creation of a DefaultJpaContext.
JpaQueryExecution applies a ConversionService to convert between low-level types such as integers, longs and byte arrays. That ConversionService also preemptively converts objects into JDK 8's Optional in case the invoked method's return type is Optional.
We now explicitly remove the converter taking care of the latter to avoid Optionals to be created before the actual result conversion is applied, as it needs to see the raw value to create DTOs or interface based projections correctly.
Use a page size of 1 to enforce a count query creation. The expected exception is only visible with Hibernate 4.1.x when a count query is issued.
Related pull request: #174.
Slightly loosened our regular expression to detect constructor expressions as previously it didn't match select expressions that contained a distinct clause.
Added guard against null values in identifiers. Null values can occur because id generation was not completed yet. Add tests for identifier derivation using @IdClass for Hibernate, OpenJPA and EclipseLink.
Original pull request: #133.
Added special handling for IdClass' typed id values to prevent
nested identifier classes from failing to be populated in JpaMetamodelEntityInformation.
Original pull request: #133.
We execute paged queries now in an optimized way. The data is obtained for each paged execution but the count query is deferred. We determine the total from the pageable and the results in which we don't hit the page size bounds (i.e. results are less than a full page without offset or results are greater 0 and less than a full page with offset). In all other cases we issue an additional count query.
Extracted the functionality to check for JPA managed types into a dedicated wrapper for the JPA Metamodel. This allows all clients to benefit from the null guards we have to put in place due to [0]. Adapted the fix introduced for DATAJPA-904 to make use of the newly created infrastructure, too.
[0] https://hibernate.atlassian.net/browse/HHH-10968
We now inspect QueryByExamplePredicateBuilder.isAndMatching() to decide whether to concatenate the predicates built using and or or.
Related tickets: DATACMNS-879.
Some persistence providers (Hibernate *cough*) return null for a ManagedType's JavaType, which we perviously didn't expect in the implementation of JpaPersistentPropertyImpl.isEntity().
We now eagerly extract all managed types from the Metamodel and gracefully skip nulls so that we don't have to look up the types repeatedly.
We now check manually defined queries for whether the projection is equal to the used alias and don't use a Tuple query in this case. This allows the manually defined queries to still define the projections manually but also the returned objects be wrapped with projection interfaces easily.
We now workaround a JPA specification violation introduced in 5.2 [0] in parameter binding. This involves removing a workaround for a bug in older Hibernate variants that returned the parameter index as String for parameters that shouldn't return a name at all. We now solve that by explicitly not considering parameter names that are purely numeric as named parameters in the first place. This also avoids producing an exception in the case of the usage of named parameters in the first place.
org.hibernate.Query was deprecated in Hibernate 5.2 but at the same time a couple of methods on it were changed in a binary incompatible way. We now explicitly detect that change in the execution of stream queries and fall back to reflection based invocation of the methods we need to call.
[0] https://hibernate.atlassian.net/browse/HHH-10803
We now use a completely reflective lookup of the Hibernate query string as well as for the Hibernate specific PersistenceProvider lookup in tests.
Added build profile for Hibernate 5.2 but it's currently not working due to Hibernate complaining about an invalid identifier mapping on CustomAbstractPersistable which is overriding the parent types property on accessor working fine on 5.1.
The build profile for 5.1 is still broken due to the fixed but yet unreleased HHH-10514 [0] and the not yet fixed HHH-10515 [1] (apparently fixed but still open and unreleased) which has been broken since 5.0.8.
[0] https://hibernate.atlassian.net/browse/HHH-10514
[1] https://hibernate.atlassian.net/browse/HHH-10515
We now make sure that the count query for derived queries using pagination uses a plain count projection and does not try to apply that on a tuple query.
Deprecated SimpleJpaRepository.readPage(…) and ….getCountQuery(…) variants for which we have more dedicated overloads taking the domain type already.
Some formatting polishing on the way.
Count queries that are executed in the context of paginated queries using Specifications now get their order specifications removed as they get rejected by some databases.
Previously we always picked the first element of the Object array returned by the Hibernate ScrollableResults. We now only do that for one element arrays to basically mimic the handling of List based query methods.
JpaPersistentEntityImpl.isEntity() currently called a method on the JPA meta-model, catching an exception to indicate the given type is not managed. We're now rather iterate over all managed types to avoid the overhead of the exception being thrown and handled immediately.
We now explicitly check the return types for queries using manually defined queries to find out whether it's a JPA managed type in the first place. Only if that's not the case we resort to a Tuple query and assume DTO mapping happening downstream.
This is necessary as a singular projection expression in the query might simply return an element of the aggregate and thus doesn't need any DTO creation. In case an unmanaged type is returned from the query method we assume DTO creation.