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.