Bad request formation in Hibernate 6

Hello.

The problem appeared after updating Hibernate to 6 (from 5.6.14.Final to 6.1.7.Final) and Spring to 3.
I have entity:

import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import java.time.OffsetDateTime;

@Getter
@Setter
@MappedSuperclass
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @CreationTimestamp
    private OffsetDateTime createdOn;
    @UpdateTimestamp
    private OffsetDateTime updatedOn;
}

and

import lombok.Getter;
import lombok.Setter;

import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.OffsetDateTime;

@Entity
@Getter
@Setter
@Table(name = "commits")
public class CommitEntity extends BaseEntity {
    private String gitlabId;
    @ManyToOne(fetch = FetchType.EAGER)
    private UserEntity user;
    private String authorEmail;
    private String authorName;
    private String title;
    @ManyToOne(fetch = FetchType.EAGER)
    private ProjectEntity project;
    private OffsetDateTime gitlabCreatedAt = OffsetDateTime.parse("2000-01-01T00:00Z");
    private String webUrl;
    private Integer additions;
    private Integer deletions;
    private Integer totalChange;
    private Boolean isMerge;
}

and

import com.vladmihalcea.hibernate.type.json.JsonType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Type;

import java.time.OffsetDateTime;
import java.util.Map;

@Entity
@Getter
@Setter
@Table(name = "projects")
public class ProjectEntity extends BaseEntity {
    private Long gitlabId;
    private OffsetDateTime gitlabCreatedAt;
    private OffsetDateTime gitlabLastActivityAt;
    private String name;
    private String description;
    @Type(JsonType.class)
    @Column(columnDefinition = "json")
    private Map<String, Float> languages;
}

When I run this code:

        final var builder = em.getCriteriaBuilder();
        final var query = builder.createQuery(ProjectStatResponse.class);

        final var commits = query.from(CommitEntity.class);
        final var projects = commits.join(CommitEntity_.project);
        commits.alias("root");

        query.select(builder.construct(
                ProjectStatResponse.class,
                projects.get(ProjectEntity_.id),
                projects.get(ProjectEntity_.name),
                builder.count(commits.get(CommitEntity_.id)),
                builder.countDistinct(commits.get(CommitEntity_.authorEmail)),
                projects.get(ProjectEntity_.languages)
        ));

        query.where(
                projects.get(ProjectEntity_.id).in(projectIds),
                builder.isFalse(commits.get(CommitEntity_.isMerge))
        );

        query.groupBy(
                projects.get(ProjectEntity_.id)
        );

        return em.createQuery(query).getResultList();

I expect something like this:

select p.id,
       p.name,
       count(c.id),
       count(distinct c.author_email),
       p.languages
from commits c
         join projects p on c.project_id = p.id
where (p.id in (?, ?, ?))
  and c.is_merge = false
group by p.id;

But I get it:

select c.project_id,
       p.name,
       count(c.id),
       count(distinct c.author_email),
       p.languages 
from commits c join projects p on p.id=c.project_id 
where c.project_id in(?,?) 
  and not(c.is_merge) 
group by 1

For some reason projects.get(ProjectEntity_.id) is not equal to p.id but equal to c.project_id.

Yeah, that’s an optimization, but it shouldn’t matter, because the join predicate p.id=c.project_id establishes equivalence.

We just recently received a report about a similar issue though: [HHH-16189] - Hibernate JIRA

1 Like