Hibernate JPA complex query

Keywords: Java Hibernate SQL

Hibernate JPA complex query

1. JPQL statement

Full name of JPQL: Java Persistence Query Language

EJB query language (EJB QL) and Java persistent query language (JPQL) introduced in EJB 2.0 are portable query languages. They aim to bind SQL syntax and simple query semantics with the expression of object-oriented expression language. Queries written in this language are portable and can be compiled into SQL on all mainstream database servers.

When using JPQL, the overall processing effect is almost the same as the syntax form of SQL, and then JPQL will be compiled into SQL statements supported by traditional relational databases when JPA is executed. Its features are similar to native SQL statements and are completely object-oriented, accessed through class names and attributes, rather than table names and table attributes.

Environmental preparation

1. Add some lombok annotations on the entity class to facilitate the preparation of test data

import lombok.*;
import lombok.experimental.Tolerate;
import javax.persistence.*;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "tb_customer")
public class Customer {

    // This construct is used to prepare for projection queries
    @Tolerate
    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "customer_id")
    private Long Id; // Customer's primary key

    @Column(name = "customer_name")
    private String name; // Customer name

    @Column(name="customer_age")
    private int age; // Customer age

    @Column(name="customer_sex")
    private boolean sex; // Customer gender

    @Column(name="customer_phone")
    private String phone; // Customer contact information

    @Column(name="customer_address")
    private String address; // Customer address
}

2. Prepare test data

    @Before
    public void initData() {
        EntityManager entityManager = JpaUtils.getEntityManager();
        entityManager.getTransaction().begin();
        Arrays.asList(
                Customer.builder().name("Sam").age(18).sex(true).phone("135000000001").address("Guangzhou").build(),
                Customer.builder().name("Mike").age(20).sex(true).phone("135000000002").address("Guangzhou").build(),
                Customer.builder().name("Nick").age(25).sex(true).phone("135000000003").address("Shenzhen").build(),
                Customer.builder().name("Hom").age(30).sex(true).phone("135000000004").address("Xi'an").build(),
                Customer.builder().name("Rachel").age(25).sex(false).phone("135000000005").address("Beijing").build(),
                Customer.builder().name("Kath").age(30).sex(true).phone("135000000006").address("Wuhan").build(),
                Customer.builder().name("Vivi").age(28).sex(false).phone("135000000007").address("Nanjing").build(),
                Customer.builder().name("Oliver").age(30).sex(true).phone("135000000008").address("Shenzhen").build(),
                Customer.builder().name("Angus").age(10).sex(false).phone("135000000009").address("Guangzhou").build(),
                Customer.builder().name("Wendy").age(15).sex(false).phone("135000000000").address("Xi'an").build()
        ).forEach(customer -> entityManager.persist(customer));
        entityManager.getTransaction().commit();
        entityManager.close();
    }

1.1. Simple query

   /**
     * Query all
     * jqpl: from Customer
     * sql: select * from c_customer
     */
    @Test
    public void testFindAll() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // 2. Query all: create a query object, which is the object to execute jqpl
        Query query = entityManager.createQuery("from Customer");

        // 3. Send the query and encapsulate the result set
        List<Customer> list = query.getResultList();
        list.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)

1.2. Alias query

    /**
     * Alias query
     *     jqpl: from Customer c
     *     jqpl: select c from Customer c
     *     sql: select * from c_customer c
     */
    @Test
    public void testFindAll2() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Query all customers, using chain call
        List<Customer> list1 = entityManager.createQuery("from Customer c").getResultList();
        list1.forEach(System.out::println);

        // Query all customers, using chain call
        List<Customer> list2 = entityManager.createQuery("select c from Customer c").getResultList();
        list2.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)
Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)

1.3 Sorting Query

    /**
     * Sort query
     *     jqpl: from Customer order by Id desc
     *     sql: select * from c_customer order by Id desc
     */
    @Test
    public void testOder() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Chain call is adopted. By default (ascending order)
        List<Customer> list1 = entityManager.createQuery("from Customer order by Id").getResultList();
        list1.forEach(System.out::println);

        // Chain call is adopted, in ascending order
        List<Customer> list2 = entityManager.createQuery("from Customer order by Id asc").getResultList();
        list2.forEach(System.out::println);

        // Chain call is adopted, and descending order is adopted
        List<Customer> list3 = entityManager.createQuery("from Customer order by Id desc").getResultList();
        list3.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    order by
        customer0_.customer_id
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)
Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    order by
        customer0_.customer_id asc
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)
Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    order by
        customer0_.customer_id desc
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)

1.4. Query criteria

    /**
     * Condition query
     *     jqpl: from Customer where sex = ?1 and name like ?2
     *     sql: SELECT * FROM c_customer where c_sex = ?1 and c_name like ?2
     *     jqpl: from Customer where sex = :aaa and name like :bbb
     *     sql: SELECT * FROM c_customer where c_sex = :aaa and c_name like :bbb
     */
    @Test
    public void testWhere() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Condition query: bind by parameter location
        Query query1 = entityManager.createQuery("from Customer where sex = ?1 and name like ?2");
        query1.setParameter(1, true);
        query1.setParameter(2, "S%");
        List<Customer> list1 = query1.getResultList();
        list1.forEach(System.out::println);

        // Condition query: bind by parameter name
        Query query2 = entityManager.createQuery("from Customer where sex = :aaa and name like :bbb");
        query2.setParameter("aaa", true);
        query2.setParameter("bbb", "S%");
        List<Customer> list2 = query2.getResultList();
        list2.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        customer0_.customer_sex=? 
        and (
            customer0_.customer_name like ?
        )
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        customer0_.customer_sex=? 
        and (
            customer0_.customer_name like ?
        )
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)

1.5. Projection query

    /**
     * Projection query
     * 1.Single field query
     * jqpl: select c.name from Customer c
     * sql: SELECT * FROM c_customer order by Id desc
     * 2.Multiple field query
     * jpql: select c.name,c.age from Customer c
     * jpql: select new Customer(c.name,c.age) from Customer c
     * sql: SELECT * FROM c_customer order by Id desc
     */
    @Test
    public void testFieldName() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Query all customer names: single field query
        Query query1 = entityManager.createQuery("select c.name from Customer c");
        List<Object> list1 = query1.getResultList();
        list1.forEach(System.out::println);

        // Query all customer names and customer ages: query multiple fields and encapsulate them into an array
        Query query2 = entityManager.createQuery("select c.name,c.age from Customer c");
        List<Object[]> list2 = query2.getResultList();
        list2.forEach(x-> System.out.println(Arrays.toString(x)));

        // Query all customer names and customer sources: query multiple fields and encapsulate them into objects
        // Please add the following two construction methods in Customer.java, otherwise the execution will fail
        // public Customer() and public Customer(String name, int age)
        Query query3 = entityManager.createQuery("select new Customer(c.name,c.age) from Customer c");
        List<Customer> list3 = query3.getResultList();
        list3.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_name as col_0_0_ 
    from
        tb_customer customer0_
Sam
Mike
Nick
Hom
Rachel
Kath
Vivi
Oliver
Angus
Wendy
Hibernate: 
    select
        customer0_.customer_name as col_0_0_,
        customer0_.customer_age as col_1_0_ 
    from
        tb_customer customer0_
[Sam, 18]
[Mike, 20]
[Nick, 25]
[Hom, 30]
[Rachel, 25]
[Kath, 30]
[Vivi, 28]
[Oliver, 30]
[Angus, 10]
[Wendy, 15]
Hibernate: 
    select
        customer0_.customer_name as col_0_0_,
        customer0_.customer_age as col_1_0_ 
    from
        tb_customer customer0_
Customer(Id=null, name=Sam, age=18, sex=false, phone=null, address=null)
Customer(Id=null, name=Mike, age=20, sex=false, phone=null, address=null)
Customer(Id=null, name=Nick, age=25, sex=false, phone=null, address=null)
Customer(Id=null, name=Hom, age=30, sex=false, phone=null, address=null)
Customer(Id=null, name=Rachel, age=25, sex=false, phone=null, address=null)
Customer(Id=null, name=Kath, age=30, sex=false, phone=null, address=null)
Customer(Id=null, name=Vivi, age=28, sex=false, phone=null, address=null)
Customer(Id=null, name=Oliver, age=30, sex=false, phone=null, address=null)
Customer(Id=null, name=Angus, age=10, sex=false, phone=null, address=null)
Customer(Id=null, name=Wendy, age=15, sex=false, phone=null, address=null)

1.6 paging query

    /**
     * Paging query
     *      jqpl : from Customer
     *      sql: select * from c_customer limit 2,5
     */
    @Test
    public void testLimit() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Paging query
        Query query = entityManager.createQuery("from Customer");
        // Starting index, number of queries per page
        query.setFirstResult(2).setMaxResults(5);
        List<Customer> list = query.getResultList();
        list.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ limit ?,
        ?
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)

1.7 group query

    /**
     * Grouping query
     *      jqpl : select count(*) from Customer
     *      sql: select count(*) from c_customer
     *
     *      jqpl : select sex,count(*) from Customer group by sex
     *      sql: select c_sex,count(*) from c_customer group by c_sex
     */
    @Test
    public void testGroupBy() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Aggregate function: count(),max(),min(),avg(),sum()
        Object object2 = entityManager.createQuery("select count(*) from Customer").getSingleResult();
        System.out.println(object2);

        // Group statistics:
        List<Object[]> list = entityManager.createQuery("select sex,count(*) from Customer group by sex").getResultList();
        list.forEach(x->System.out.println(Arrays.toString(x)));

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

View log:

Hibernate: 
    select
        count(*) as col_0_0_ 
    from
        tb_customer customer0_
10
Hibernate: 
    select
        customer0_.customer_sex as col_0_0_,
        count(*) as col_1_0_ 
    from
        tb_customer customer0_ 
    group by
        customer0_.customer_sex
[false, 4]
[true, 6]

1.8. Multi table query

    @Test
    public void testXXJoin() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Inner connection
        List<Object[]> list1 = entityManager.createQuery("from Customer c inner join c.linkMans").getResultList();
        list1.forEach(x->System.out.println(Arrays.toString(x)));

        // Urgent inner connection (unique to hibernate, which encapsulates the data of another object into this object)
        List<Customer> list2 = entityManager.createQuery("select distinct c from Customer c inner join fetch c.linkMans").getResultList();
        list2.forEach(System.out::println);

        // Left outer connection
        List<Object[]> list3 = entityManager.createQuery("from Customer c left outer join c.linkMans").getResultList();
        list3.forEach(x->System.out.println(Arrays.toString(x)));

        // Urgent left external connection (unique to hibernate, encapsulating the data of another object into this object)
        List<Customer> list4 = entityManager.createQuery("select distinct c from Customer c left outer join fetch c.linkMans").getResultList();
        list4.forEach(System.out::println);

        // Right outer connection
        List<Object[]> list5 = entityManager.createQuery("from Customer c right outer join c.linkMans").getResultList();
        list5.forEach(x->System.out.println(Arrays.toString(x)));

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

2. Native SQL query

Sometimes, improper use of JPQL will lead to that the converted SQL is not as good as ideal, or SQL optimization is required for specific occasions, and native SQL queries are still needed. The createNativeQuery method of the EntityManager object can implement very complex queries, but the query results need to be entity mapped, and cannot cross the database.

  • Get the native SQL query object: Query createNativeQuery(String var1, Class var2);

  • Compared with JPQL, you only need to replace the query object method with createNativeQuery() from createQuery() (the passed in value becomes a native SQL and class object)

package query;

import entity.Customer;
import org.junit.Before;
import org.junit.Test;
import util.JpaUtils;
import javax.persistence.*;
import java.util.Arrays;
import java.util.List;

public class JpaSqlTest {

    @Before
    public void initData() {
        EntityManager entityManager = JpaUtils.getEntityManager();
        entityManager.getTransaction().begin();
        Arrays.asList(
                Customer.builder().name("Sam").age(18).sex(true).phone("135000000001").address("Guangzhou").build(),
                Customer.builder().name("Mike").age(20).sex(true).phone("135000000002").address("Guangzhou").build(),
                Customer.builder().name("Nick").age(25).sex(true).phone("135000000003").address("Shenzhen").build(),
                Customer.builder().name("Hom").age(30).sex(true).phone("135000000004").address("Xi'an").build(),
                Customer.builder().name("Rachel").age(25).sex(false).phone("135000000005").address("Beijing").build(),
                Customer.builder().name("Kath").age(30).sex(true).phone("135000000006").address("Wuhan").build(),
                Customer.builder().name("Vivi").age(28).sex(false).phone("135000000007").address("Nanjing").build(),
                Customer.builder().name("Oliver").age(30).sex(true).phone("135000000008").address("Shenzhen").build(),
                Customer.builder().name("Angus").age(10).sex(false).phone("135000000009").address("Guangzhou").build(),
                Customer.builder().name("Wendy").age(15).sex(false).phone("135000000000").address("Xi'an").build()
        ).forEach(customer -> entityManager.persist(customer));
        entityManager.getTransaction().commit();
        entityManager.close();
    }

    /**
     * Query all sql: SELECT * FROM tb_customer
     */
    @Test
    public void testFindAll() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // 2. Query all: create a query object, which is the object to execute jqpl
        String sql = "select * from tb_customer";
        Query query = entityManager.createNativeQuery(sql, Customer.class);

        // 3. Send the query and encapsulate the result set
        List<Customer> list = query.getResultList();
        list.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

    /**
     * Sort query sql: select * from tb_customer order by customer_id desc
     */
    @Test
    public void testOder() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Chain call is adopted. By default (ascending order)
        String sql1 = "select * from tb_customer order by customer_id";
        List<Customer> list1 = entityManager.createNativeQuery(sql1, Customer.class).getResultList();
        list1.forEach(System.out::println);

        // Chain call is adopted, in ascending order
        String sql2 = "select * from tb_customer order by customer_id asc ";
        List<Customer> list2 = entityManager.createNativeQuery(sql2, Customer.class).getResultList();
        list2.forEach(System.out::println);

        // Chain call is adopted, and descending order is adopted
        String sql3 = "select * from tb_customer order by customer_id desc";
        List<Customer> list3 = entityManager.createNativeQuery(sql3, Customer.class).getResultList();
        list3.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

    /**
     * Condition query
     *     sql: SELECT * FROM tb_customer where customer_sex = ?1 and customer_name like ?2
     *     sql: SELECT * FROM tb_customer where customer_sex = :aaa and customer_name like :bbb
     */
    @Test
    public void testWhere() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Condition query: bind by parameter location
        String sql1 = "SELECT * FROM tb_customer where customer_sex = ?1 and customer_name like ?2";
        Query query1 = entityManager.createNativeQuery(sql1, Customer.class);
        query1.setParameter(1, true);
        query1.setParameter(2, "S%");
        List<Customer> list1 = query1.getResultList();
        list1.forEach(System.out::println);

        // Condition query: bind by parameter name
        String sql2 = "SELECT * FROM tb_customer where customer_sex = :aaa and customer_name like :bbb";
        Query query2 = entityManager.createNativeQuery(sql2, Customer.class);
        query2.setParameter("aaa", true);
        query2.setParameter("bbb", "S%");
        List<Customer> list2 = query2.getResultList();
        list2.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

    /**
     * Paging query sql: select * from tb_customer limit 2,5
     */
    @Test
    public void testLimit() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Paging query
        String sql = "select * from tb_customer limit 2,5";
        Query query = entityManager.createNativeQuery(sql, Customer.class);
        // Starting index, number of queries per page
        //query.setFirstResult(2).setMaxResults(5);
        List<Customer> list = query.getResultList();
        list.forEach(System.out::println);

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }

    /**
     * Grouping query
     *      sql: select count(*) from tb_customer
     *      sql: select c_sex,count(*) from tb_customer group by c_sex
     */
    @Test
    public void testGroupBy() {
        // 1. Get entityManager object & & start transaction
        EntityManager entityManager = JpaUtils.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        // Aggregate function: count(),max(),min(),avg(),sum()
        String sql1 = "select count(*) from tb_customer";
        Object object2 = entityManager.createNativeQuery(sql1).getSingleResult();
        System.out.println(object2);

        // Group statistics:
        String sql2 = "select customer_sex,count(*) from tb_customer group by customer_sex";
        List<Object[]> list = entityManager.createNativeQuery(sql2).getResultList();
        list.forEach(x->System.out.println(Arrays.toString(x)));

        // 4. Commit transaction & & release resources
        transaction.commit();
        entityManager.close();
    }
}

Check the log (select one at random): you can find that the SQL statement is still somewhat different from that generated by JPQL

Hibernate: 
    select
        * 
    from
        tb_customer
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)

3. Criteria query

JPA Criteria API: https://www.cnblogs.com/xingqi/p/3929386.html

1. Through JPA's Criteria API:

  1. EntityManager get CriteriaBuilder
  2. CriteriaBuilder creates CriteriaQuery
  3. CriteriaQuery specifies the table to query to get the Root (Root represents the table to query)
  4. CriteriaBuilder creates a condition Predicate, which is equivalent to the where condition of SQL. Multiple predicates can be used for and, or operations
  5. Create TypedQuery through EntityManager
  6. TypedQuery executes the query and returns the result

2. Detailed steps for building basic objects:

  1. The CriteriaBuilder object can be obtained through the EntityManager.getCriteriaBuilder() or EntityManagerFactory.getCriteriaBuilder() methods
  2. The CriteriaQuery instance can be obtained by calling the CriteriaBuilder.createQuery() or createuplequery() methods
  3. The Root instance can be obtained by calling the CriteriaQuery.from() method

3. Filter conditions:

  1. The filter condition is applied to the FROM clause of the SQL statement. In Criteria query, query Criteria are applied to Criteria query objects through Predicate or Expression instances
  2. These conditions are applied to the CriteriaQuery object using the CriteriaQuery.where() method
  3. CriteriaBuilder is also used as the factory of the Predicate instance to create the Predicate object by calling the conditional methods of CriteriaBuilder (equal, notEqual, gt, ge, lt, le, between, like, etc.).
  4. Composite Predicate statements can be built using the and, or, and not methods of CriteriaBuilder

Prepare test data

import lombok.*;
import lombok.experimental.Tolerate;
import javax.persistence.*;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "tb_customer")
public class Customer {

    // This construct is used to prepare for projection queries
    @Tolerate
    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "customer_id")
    private Long Id; // Customer's primary key

    @Column(name = "customer_name")
    private String name; // Customer name

    @Column(name="customer_age")
    private int age; // Customer age

    @Column(name="customer_sex")
    private boolean sex; // Customer gender

    @Column(name="customer_phone")
    private String phone; // Customer contact information

    @Column(name="customer_address")
    private String address; // Customer address
}
    @Before
    public void initData() {
        EntityManager entityManager = JpaUtils.getEntityManager();
        entityManager.getTransaction().begin();
        Arrays.asList(
                Customer.builder().name("Sam").age(18).sex(true).phone("135000000001").address("Guangzhou").build(),
                Customer.builder().name("Mike").age(20).sex(true).phone("135000000002").address("Guangzhou").build(),
                Customer.builder().name("Nick").age(25).sex(true).phone("135000000003").address("Shenzhen").build(),
                Customer.builder().name("Hom").age(30).sex(true).phone("135000000004").address("Xi'an").build(),
                Customer.builder().name("Rachel").age(25).sex(false).phone("135000000005").address("Beijing").build(),
                Customer.builder().name("Kath").age(30).sex(true).phone("135000000006").address("Wuhan").build(),
                Customer.builder().name("Vivi").age(28).sex(false).phone("135000000007").address("Nanjing").build(),
                Customer.builder().name("Oliver").age(30).sex(true).phone("135000000008").address("Shenzhen").build(),
                Customer.builder().name("Angus").age(10).sex(false).phone("135000000009").address("Guangzhou").build(),
                Customer.builder().name("Wendy").age(15).sex(false).phone("135000000000").address("Xi'an").build()
        ).forEach(customer -> entityManager.persist(customer));
        entityManager.getTransaction().commit();
        entityManager.close();
    }

3.1. Query all

    /**
     * Query all (simple)
     * sql: select * from tb_customer
     */
    @Test
    public void testFindAll() {
        // Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        // 1. Get CriteriaBuilder from entitymanager
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        // 2.CriteriaBuilder creates CriteriaQuery
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        // 3.CriteriaQuery specifies the table to be queried to get the Root, which represents the table to be queried
        criteriaQuery.from(Customer.class);
        TypedQuery<Customer> query = entityManager.createQuery(criteriaQuery);
        List<Customer> list = query.getResultList();
        list.forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

    /**
     * Query all (full)
     * sql: select * from tb_customer
     */
    @Test
    public void testFindAll2() {
        // Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        // 1. Get CriteriaBuilder from entitymanager
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        // 2.CriteriaBuilder creates CriteriaQuery
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        // 3.CriteriaQuery specifies the table to be queried to get the Root, which represents the table to be queried
        Root<Customer> from = criteriaQuery.from(Customer.class);
        // This step can be omitted, and the CriteriaQuery object is still returned
        CriteriaQuery<Customer> select = criteriaQuery.select(from);
        // If the previous step is omitted, the criteriaQuery is passed in
        TypedQuery<Customer> query = entityManager.createQuery(select);
        List<Customer> list = query.getResultList();
        list.forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)
Customer(Id=10, name=Wendy, age=15, sex=false, phone=135000000000, address=Xi'an)

3.2. Projection query

There are two ways to get CriteriaQuery instances:

  1. CriteriaBuilder.createQuery(): return criteriaquery < T >
  2. Criteriabuilder. Createtablequery(): returns criteriaquery < tuple >

Differences between the two methods:

  1. createQuery(): mainly used to query SQL corresponding to entity class fields
  2. createTupleQuery(): you can query field data (count, sum, max, min, avg, etc.) other than entity class fields. group by is used more often, generally combined with the criteriaQuery.multiselect() method

Method 1: CriteriaBuilder.createQuery()

    /**
     * Projection query - criteriaBuilder.createQuery(Customer.class)
     * sql: select customer_name, customer_age from tb_customer
     * be careful:
     *   The constructor must be public Customer(String name, int age) in the entity class, otherwise an error will be reported
     * You can also use another method:
     *   criteriaBuilder.createTupleQuery() // Create a query and return the tuple type. Tuple contains multiple TupleElements
     */
    @Test
    public void testFindAllMultiSelect() {
        // Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        // 1.CriteriaBuilder security query creation factory
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        // 2.CriteriaQuery security query subject sentence
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        // 3.Root defines the types that can appear in the From clause of the query
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // You must have this constructor: public Customer(String name, int age), otherwise an error will be reported
        criteriaQuery.multiselect(from.get("name"), from.get("age"));
        TypedQuery<Customer> query = entityManager.createQuery(criteriaQuery);
        List<Customer> list = query.getResultList();
        list.forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_name as col_0_0_,
        customer0_.customer_age as col_1_0_ 
    from
        tb_customer customer0_
Customer(Id=null, name=Sam, age=18, sex=false, phone=null, address=null)
Customer(Id=null, name=Mike, age=20, sex=false, phone=null, address=null)
Customer(Id=null, name=Nick, age=25, sex=false, phone=null, address=null)
Customer(Id=null, name=Hom, age=30, sex=false, phone=null, address=null)
Customer(Id=null, name=Rachel, age=25, sex=false, phone=null, address=null)
Customer(Id=null, name=Kath, age=30, sex=false, phone=null, address=null)
Customer(Id=null, name=Vivi, age=28, sex=false, phone=null, address=null)
Customer(Id=null, name=Oliver, age=30, sex=false, phone=null, address=null)
Customer(Id=null, name=Angus, age=10, sex=false, phone=null, address=null)
Customer(Id=null, name=Wendy, age=15, sex=false, phone=null, address=null)

Method 2: criteriabuilder. Createtablequery ()

    /**
     * Projection query - criteriabuilder. Createtablequery()
     * sql: select customer_name, customer_age from tb_customer
     * be careful:
     *   Use: returns a tuple query without error
     */
    @Test
    public void testFindAllMultiSelect2() {
        // Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        // 1.CriteriaBuilder security query creation factory
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        // 2.CriteriaQuery security query subject sentence
        CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery();
        // 3.Root defines the types that can appear in the From clause of the query
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // You need to alias the field, otherwise you cannot get data through tuple.get(field)
        criteriaQuery.multiselect(from.get("name").alias("name"), from.get("age").alias("age"));
        TypedQuery<Tuple> query = entityManager.createQuery(criteriaQuery);
        List<Tuple> list = query.getResultList();
        // name = list.get(0).get(0); age = list.get(0).get(1)
        list.forEach(x-> System.out.println(x.get("name")+","+x.get("age")));

        // Release resources
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_name as col_0_0_,
        customer0_.customer_age as col_1_0_ 
    from
        tb_customer customer0_
Sam,18
Mike,20
Nick,25
Hom,30
Rachel,25
Kath,30
Vivi,28
Oliver,30
Angus,10
Wendy,15

3.3. Query criteria

1. Single condition query

    /**
     * Condition query - single condition
     * Predicate Filter condition
     * sql: select * from tb_customer where customer_name = 'Sam'
     */
    @Test
    public void testFindWhereEQ() {
        // Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        Root<Customer> from = criteriaQuery.from(Customer.class);
        criteriaQuery.select(from);// Define the query, and this row can be omitted

        // 4. Predict or predict [] filter conditions
        Predicate predicate = criteriaBuilder.equal(from.get("name"), "Sam");
        criteriaQuery.where(predicate);
        // Using chain call
        entityManager.createQuery(criteriaQuery).getResultList().forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        customer0_.customer_name=?
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)

2. Multi condition query

Connection, disconnection and Predicate [] comparison:

  1. Criteriabuilder. Junction(): logical and
  2. Criteriabuilder. Disconnection(): logical or (or)
  3. Predicate []: logical and (and)

The difference between Predicate [] and conjunction: Predicate [] normally splices all conditions in the array with and, while conjunction automatically adds 1 = 1 after where, and then splices the conditions

Operation example:

    /**
     * Condition query - and, equals, lt
     * Predicate[] Multiple filter conditions (personal recommendation)
     * sql: select * from tb_customer where customer_name = 'Sam' and c_age < 20
     */
    @Test
    public void testFindWhereEqGt() {
        // 1. Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // 4. Predict [] filter criteria: set a set of query criteria
        List<Predicate> predicates = new ArrayList<>();
        predicates.add(criteriaBuilder.equal(from.get("name"), "Sam"));
        predicates.add(criteriaBuilder.lt(from.get("age"), 20));
        criteriaQuery.where(predicates.toArray(new Predicate[]{}));// new Predicate[]{}=>new Predicate[predicates.size()]
        // Using chain call
        entityManager.createQuery(criteriaQuery).getResultList().forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

    /**
     * Condition query - like, and, equal, lt
     * Predicate Multiple filter conditions - criteriabuilder. Junction() / / logical and
     *                        - criteriaBuilder.disjunction() // Logical or
     * sql: select * from tb_customer where 1=1 and customer_name like 'S%' and customer_name = 'Sam' and customer_age < 20
     */
    @Test
    public void testFindWhereEqGt2() {
        // 1. Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // 4. Predict [] filter criteria: set a set of query criteria
        Predicate predicate = criteriaBuilder.conjunction();
        // Filter condition - like: and customer_name like S%
        predicate= criteriaBuilder.and(predicate, criteriaBuilder.like(from.get("name"), "S%"));
        // Filter condition - equal: and customer_name like S% and customer_name = 'Sam'
        predicate= criteriaBuilder.and(predicate, criteriaBuilder.equal(from.get("name"), "Sam"));
        // Filter criteria - lt: and customer_ name like S% and customer_ name = 'Sam' and customer_ age < 20
        predicate= criteriaBuilder.and(predicate, criteriaBuilder.lt(from.get("age"), 20));
        criteriaQuery.where(predicate);
        // Using chain call
        entityManager.createQuery(criteriaQuery).getResultList().forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

    /**
     * Condition query - not in, between
     * Predicate Multiple filter conditions - criteriabuilder. Junction() / / logical and
     *                        - criteriaBuilder.disjunction() // Logical or
     * sql: select * from tb_customer where 1=1 and customer_age not in (18 , 20) and customer_id between 5 and 9
     */
    @Test
    public void testFindWhereNotInBetween() {
        // 1. Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // 4. Predict filter multiple conditions
        Predicate predicate = criteriaBuilder.conjunction();
        // Filter condition - in: customer_age not in (18 , 20)
        predicate= criteriaBuilder.and(predicate, from.get("age").in(Arrays.asList(18, 20)).not());
        // Filter condition - in: customer_age not in (18 , 20) and customer_id between 5 and 9
        predicate= criteriaBuilder.and(predicate, criteriaBuilder.between(from.get("Id"), 5,9));
        criteriaQuery.where(predicate);
        // Using chain call
        entityManager.createQuery(criteriaQuery).getResultList().forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

View log: (condition query - multiple conditions (and, equals, lt))

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        customer0_.customer_name=? 
        and customer0_.customer_age<20
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)

View log: (condition query - like, and, equal, lt)

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        1=1 
        and (
            customer0_.customer_name like ?
        ) 
        and customer0_.customer_name=? 
        and customer0_.customer_age<20
Customer(Id=1, name=Sam, age=18, sex=true, phone=135000000001, address=Guangzhou)

View log: (condition query - not in, between)

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        1=1 
        and (
            customer0_.customer_age not in  (
                18 , 20
            )
        ) 
        and (
            customer0_.customer_id between 5 and 9
        )
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)
Customer(Id=8, name=Oliver, age=30, sex=true, phone=135000000008, address=Shenzhen)
Customer(Id=9, name=Angus, age=10, sex=false, phone=135000000009, address=Guangzhou)

3.4 Sorting Query

You can set a single order and multiple orders

    /**
     * Sort query
     * sql: select * from tb_customer where 1=1 and customer_age in (18 , 28) and customer_id between 2 and 4 order by customer_id desc
     */
    @Test
    public void testFindWhereInBetweenOderBy() {
        // 1. Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // 4. Predict or predict [] filter conditions
        Predicate age = from.get("age").in(18, 28);
        Predicate id = criteriaBuilder.between(from.get("Id"), 2, 10);
        criteriaQuery.where(Arrays.asList(age, id).toArray(new Predicate[]{}));
        // Sort (descending)
        Order idOrder = criteriaBuilder.desc(from.get("Id"));
        criteriaQuery.orderBy(idOrder);
        // Multiple orders can be set. Sort by Id in descending order and then by age in ascending order
        // criteriaQuery.orderBy(criteriaBuilder.desc(from.get("Id")),criteriaBuilder.asc(from.get("age")));
        // Using chain call
        entityManager.createQuery(criteriaQuery).getResultList().forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        (
            customer0_.customer_age in (
                18 , 28
            )
        ) 
        and (
            customer0_.customer_id between 2 and 10
        ) 
    order by
        customer0_.customer_id desc
Customer(Id=7, name=Vivi, age=28, sex=false, phone=135000000007, address=Nanjing)

3.5 paging query

    /**
     * Paging query
     * sql: select * from tb_customer where 1=1 and customer_id between 2 and 10 limit 0,5
     */
    @Test
    public void testFindWhereBetween() {
        // 1. Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // 4. Predict or predict [] filter conditions
        Predicate id = criteriaBuilder.between(from.get("Id"), 2, 10);
        criteriaQuery.where(Arrays.asList(id).toArray(new Predicate[]{}));

        // It adopts chain call and paging query
        entityManager.createQuery(criteriaQuery)
                .setFirstResult(0) // Start index
                .setMaxResults(5)  // Number of queries per page
                .getResultList()
                .forEach(System.out::println);

        // Release resources
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_address as customer2_2_,
        customer0_.customer_age as customer3_2_,
        customer0_.customer_name as customer4_2_,
        customer0_.customer_phone as customer5_2_,
        customer0_.customer_sex as customer6_2_ 
    from
        tb_customer customer0_ 
    where
        customer0_.customer_id between 2 and 10 limit ?
Customer(Id=2, name=Mike, age=20, sex=true, phone=135000000002, address=Guangzhou)
Customer(Id=3, name=Nick, age=25, sex=true, phone=135000000003, address=Shenzhen)
Customer(Id=4, name=Hom, age=30, sex=true, phone=135000000004, address=Xi'an)
Customer(Id=5, name=Rachel, age=25, sex=false, phone=135000000005, address=Beijing)
Customer(Id=6, name=Kath, age=30, sex=true, phone=135000000006, address=Wuhan)

3.6 group query

group by:

  1. Tuple type for creating query: criteriaBuilder.createTupleQuery()
  2. Set multiple selection results: criteriaQuery.multiselect()
  3. Set an alias for the field (this is not necessary and can be set for convenience)
    /**
     * Grouping query
     * sql: select c_name,count(c_name),max(c_age),min(c_age),sum(c_age),avg(c_age) from c_customer group by c_name
     */
    @Test
    public void testFindGroupBy() {
        // 1. Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery();
        Root<Customer> from = criteriaQuery.from(Customer.class);

        // . alias("name") alias
        criteriaQuery.multiselect(
                from.get("name").alias("name"),
                criteriaBuilder.count(from.get("name")).alias("count"),
                criteriaBuilder.max(from.get("age")).alias("max"),
                criteriaBuilder.min(from.get("age")).alias("min"),
                criteriaBuilder.sum(from.get("age")).alias("sum"),
                criteriaBuilder.avg(from.get("age")).alias("avg"));
        criteriaQuery.groupBy(from.get("name"));
        // criteriaQuery.having(criteriaBuilder.disjunction());

        // Using chain call
        entityManager.createQuery(criteriaQuery).getResultList()
                .forEach(x-> System.out.println(
                        x.get("name") + "," +
                        x.get("count") + "," +
                        x.get("max") + "," +
                        x.get("min") + "," +
                        x.get("sum") + "," +
                        x.get("avg"))
                );

        // Release resources
        entityManager.close();
    }

View log:

Hibernate: 
    select
        customer0_.customer_name as col_0_0_,
        count(customer0_.customer_name) as col_1_0_,
        max(customer0_.customer_age) as col_2_0_,
        min(customer0_.customer_age) as col_3_0_,
        sum(customer0_.customer_age) as col_4_0_,
        avg(customer0_.customer_age) as col_5_0_ 
    from
        tb_customer customer0_ 
    group by
        customer0_.customer_name
Angus,1,10,10,10,10.0
Hom,1,30,30,30,30.0
Kath,1,30,30,30,30.0
Mike,1,20,20,20,20.0
Nick,1,25,25,25,25.0
Oliver,1,30,30,30,30.0
Rachel,1,25,25,25,25.0
Sam,1,18,18,18,18.0
Vivi,1,28,28,28,28.0
Wendy,1,15,15,15,15.0

3.7. Multi table query

It is recommended to refer to the entity class test in the many to one tutorial first, or you can directly use the entity class given below

/**
 * Multi party / foreign key table
 * This example adopts one-way many to one. Therefore, you only need to configure multiple parties
 */
@Data
@Entity
@Table(name = "t_many")
public class Many {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "many_id")
    private Long manyId;
    @Column(name = "many_name")
    private String manyName;

    @ManyToOne
    @JoinColumn(name="one_id")
    private One one;
}


/**
 * One party / primary key table
 * This example adopts one-way many to one. Therefore, you only need to configure multiple parties
 */
@Data
@Entity
@Table(name = "t_one")
public class One {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "one_id")
    private Long oneId;
    @Column(name = "one_type")
    private String oneType;
}

Test code:

    /**
     * Multi table Association: unidirectional many to one
     * Data insertion
     */
    @Test
    public void testSaveJoinTable() {
        // 1. Get entityManager object
        EntityManager entityManager = JpaUtils.getEntityManager();
        // Open transaction
        entityManager.getTransaction().begin();

        // Insert a piece of data (primary key table) into One
        One one = new One();
        one.setOneType("junior middle school");
        entityManager.persist(one);

        // Insert three pieces of data for Many (foreign key table)
        Many manyA = new Many();
        manyA.setManyName("First day");
        manyA.setOne(one);
        entityManager.persist(manyA);
        Many manyB = new Many();
        manyB.setManyName("The second day of junior high school");
        manyB.setOne(one);
        entityManager.persist(manyB);
        Many manyC = new Many();
        manyC.setManyName("Junior three");
        manyC.setOne(one);
        entityManager.persist(manyC);

        // Commit transaction
        entityManager.getTransaction().commit();
    }

    /**
     * Root Represents the table to be queried (the Many table is represented here)
     * Join Represents the connection query (table), which is obtained through the root object (Join represents the associated table One table)
     * During the creation process, the first parameter is the attribute name of the associated object, and the second parameter is the connection query method (left, inner, right)
     * JoinType.INNER: Inner connection, JoinType.LEFT: left outer connection, JoinType.RIGHT: right outer connection
     * After using multi table Association, Join has the function of root. You can join.get("object attribute name")
     * be careful! be careful! be careful:
     *     Root: It represents the Many table, so you can only get the attributes or fields of the Many table through root.get()
     *     join: It represents the One table. Although it is an associated query, it only represents the associated One table and can only obtain the properties of One
     *     If root/join obtains attributes or fields other than its own table, the following error will be reported:
     *     Unable to locate Attribute  with the the given name [categoryType] on this ManagedType[XXX]
     *     If there is a third table Association, use join.join() to pass it down.
     */
    @Test
    public void testFindJoinTable() {
        // 1. Get entityManager object & & the transaction is omitted here
        EntityManager entityManager = JpaUtils.getEntityManager();

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Many> criteriaQuery = criteriaBuilder.createQuery(Many.class);

        // Important: root can only represent the Many table, and join can only represent the One table.
        Root<Many> root = criteriaQuery.from(Many.class);
        Join<Many, One> join = root.join("one", JoinType.LEFT);

        Path<Object> type = join.get("oneType");
        Path<Object> manyName = root.get("manyName");
        Predicate p1 = criteriaBuilder.equal(type, "junior middle school");
        Predicate p2 = criteriaBuilder.equal(manyName, "First day");
        Predicate predicate = criteriaBuilder.and(p1, p2);
        criteriaQuery.where(predicate);
        TypedQuery<Many> query = entityManager.createQuery(criteriaQuery);
        List<Many> resultList = query.getResultList();
        resultList.forEach(System.out::println);
    }

View log:

Hibernate: 
    select
        many0_.many_id as many_id1_3_,
        many0_.many_name as many_nam2_3_,
        many0_.one_id as one_id3_3_ 
    from
        t_many many0_ 
    left outer join
        t_one one1_ 
            on many0_.one_id=one1_.one_id 
    where
        one1_.one_type=? 
        and many0_.many_name=?
Hibernate: 
    select
        one0_.one_id as one_id1_4_0_,
        one0_.one_type as one_type2_4_0_ 
    from
        t_one one0_ 
    where
        one0_.one_id=?
Many(manyId=1, manyName=First day, one=One(oneId=1, oneType=junior middle school))

Posted by Meissa on Fri, 10 Sep 2021 02:39:57 -0700