Skip to content

Commit

Permalink
HHH-14585 size() HQL function discards '@where' clause
Browse files Browse the repository at this point in the history
  • Loading branch information
mrizzi authored and fax4ever committed May 11, 2021
1 parent 0c79d1d commit 51529f5
Showing 1 changed file with 195 additions and 0 deletions.
@@ -0,0 +1,195 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

package org.hibernate.test.hql.size;

import org.hibernate.annotations.ResultCheckStyle;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;

import org.hibernate.testing.TestForIssue;
import org.junit.After;
import org.junit.Test;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;

@TestForIssue(jiraKey = "HHH-14585")
public class WhereClauseOrderBySizeTest extends BaseEntityManagerFunctionalTestCase {

@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Person.class, Book.class };
}

@Test
public void testSizeAsOrderByExpression() {
doInJPA(
this::entityManagerFactory,
entityManager -> {
// initial situation: Alice has 1 book, Bob none
final Person alice = new Person( "Alice" );
entityManager.persist( alice );

final Book book1 = new Book();
book1.setOwner( alice );
entityManager.persist( book1 );

final Person bob = new Person( "Bob" );
entityManager.persist( bob );

final TypedQuery<Person> orderByBroken = entityManager.createQuery(
"SELECT p FROM Person p ORDER BY size(p.books) DESC",
Person.class
);
final TypedQuery<Person> orderByWorking = entityManager.createQuery(
"SELECT p FROM Person p ORDER BY p.books.size DESC",
Person.class
);

List<Person> dbPeopleBroken = orderByBroken.getResultList();
List<Person> dbPeopleWorking = orderByWorking.getResultList();
assertEquals( Arrays.asList( alice, bob ), dbPeopleWorking );
assertEquals( dbPeopleWorking, dbPeopleBroken );

// add 2 books to Bob
final Book book2 = new Book();
book2.setOwner( bob );
entityManager.persist( book2 );

final Book book3 = new Book();
book3.setOwner( bob );
entityManager.persist( book3 );

dbPeopleBroken = orderByBroken.getResultList();
dbPeopleWorking = orderByWorking.getResultList();
assertEquals( Arrays.asList( bob, alice ), dbPeopleWorking );
assertEquals( dbPeopleWorking, dbPeopleBroken );

// remove (soft-deleting) both Bob's books
entityManager.remove( book2 );
entityManager.remove( book3 );

// result lists are not equal anymore
dbPeopleBroken = orderByBroken.getResultList();
dbPeopleWorking = orderByWorking.getResultList();
assertEquals( Arrays.asList( alice, bob ), dbPeopleWorking );
assertEquals( dbPeopleWorking, dbPeopleBroken );
}
);
}

@After
public void cleanupDatabase() {
doInJPA(
this::entityManagerFactory,
entityManager -> {
for ( Book book : entityManager.createQuery( "from Book", Book.class ).getResultList() ) {
entityManager.remove( book );
}
for ( Person person : entityManager.createQuery( "from Person", Person.class ).getResultList() ) {
entityManager.remove( person );
}
}
);
}

@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "owner", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Book> books = new ArrayList<>();

public Person(String name) {
this.name = name;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<Book> getBooks() {
return books;
}

public void setBooks(List<Book> books) {
this.books = books;
}

@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

@Entity(name = "Book")
@SQLDelete(sql = "UPDATE Book SET deleted = true WHERE id = ?", check = ResultCheckStyle.COUNT)
@Where(clause = "deleted = false")
public static class Book {
@Id
@GeneratedValue
private Long id;
private Boolean deleted = false;
@ManyToOne
private Person owner;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Boolean getDeleted() {
return deleted;
}

public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}

public Person getOwner() {
return owner;
}

public void setOwner(Person owner) {
this.owner = owner;
}
}
}

0 comments on commit 51529f5

Please sign in to comment.