jpa之jpql查询

JPQL介绍
JPQL语言,即 Java Persistence Query Language 的简称。JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的 SQL 查询,从而屏蔽不同数据库的差异。如果会hibernate的hql查询,那么jpql会上手的很快。
JPQL语言的语句可以是 select 语句、update 语句或delete语句,它们都通过 Query 接口封装执行。
Query接口封装了执行数据库查询的相关方法。调用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以获得查询对象,进而可调用 Query 接口的相关方法来执行查询操作。

实体类User和Order如下

@Entity
@Table(name = "t_user")
public class User {

    @Id//必须指定主键
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @Column(name="user_name")
    private String userName;

    private String password;

    private String telephone;

    private String email;

    @Column(name="create_time")
    @Temporal(TemporalType.DATE)
    private Date createTime;

    @JoinColumn(name="user_id")
    @OneToMany(cascade=CascadeType.REMOVE)
    private Set orders = new HashSet<>();

    //映射必须定义个空构造器
    public User() {
    }

    public User(String userName, String password, String telephone, String email, Date createTime) {
        this.userName = userName;
        this.password = password;
        this.telephone = telephone;
        this.email = email;
        this.createTime = createTime;
    }

    public String getUserInfo(){
        return "username:"+this.userName+",email:"+this.email;
    }
    get、set、toString方法
}
@Entity
@Table(name = "t_order")
public class Order {
    @Id
    @GeneratedValue
    private Long id;
    //付款金额
    private Integer payment;
    //支付方式 0:支付宝 1:微信
    private Integer channel;
    //支付状态
    private Integer status=0;
    //创建时间
    @Column(name="create_time")
    @Temporal(TemporalType.DATE)
    private Date createTime;

    //单向多对1,很智能,数据库中会出现关联字段user_id,或者自己指定外键列名
    @ManyToOne(targetEntity=User.class,fetch=FetchType.LAZY)
    private User user;
    public Order() {
    }
    public Order(Integer payment, Integer channel, Integer status, Date createTime) {
        this.payment = payment;
        this.channel = channel;
        this.status = status;
        this.createTime = createTime;
    }
    get、set、toString方法
}

数据库表如下:
jpa之jpql查询_第1张图片

public class JpqlTest {
    private EntityManager entityManager;
    private EntityManagerFactory entityManagerFactory;
    private EntityTransaction transaction;

    @Before
    public void init(){
        entityManagerFactory = Persistence.createEntityManagerFactory("jpa-2");
        entityManager = entityManagerFactory.createEntityManager();
        transaction = entityManager.getTransaction();
        transaction.begin();
    }
    @After
    public void destory(){
        transaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }
    @Test
    /*
     * 创建查询对象三种方式:1、createQuery();
     * 获取单一(实体类)查询结果:query.getSingleResult()
     */
    public void testJpql(){
        //1、创建jpql语句(SELECT u可以省去)
        String jpql = "SELECT u FROM User u WHERE u.id=?";
        //2、创建查询对象
        Query query = entityManager.createQuery(jpql);
        //3、设置查询参数,位置从1开始
        query.setParameter(1, 18l);
        //4、执行查询(返回单一实体查询结果)
        User user = (User)query.getSingleResult();
        System.out.println(user.getUserInfo());
        System.out.println(user.getOrders().size());
    }
}
控制台输出:
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.create_time as create_t2_2_,
        user0_.email as email3_2_,
        user0_.password as password4_2_,
        user0_.telephone as telephon5_2_,
        user0_.user_name as user_nam6_2_ 
    from
        t_user user0_ 
    where
        user0_.id=?
username:Hession,email:[email protected]
Hibernate: 
    select
        orders0_.user_id as user_id6_2_1_,
        orders0_.id as id1_1_1_,
        orders0_.id as id1_1_0_,
        orders0_.channel as channel2_1_0_,
        orders0_.create_time as create_t3_1_0_,
        orders0_.payment as payment4_1_0_,
        orders0_.status as status5_1_0_,
        orders0_.user_id as user_id6_1_0_ 
    from
        t_order orders0_ 
    where
        orders0_.user_id=?
2

一对多默认就是延迟加载,所以会发送2条sql语句分别查询User信息和Order信息。
api:

  • entityManager.createQuery(jpql):创建jpql查询对象
  • query.setParameter(position, id):设置查询参数
  • query.getSingleResult():执行查询,返回单一实体

    注:jpql的编写基本跟hql一样,都是面向对象查询

    @Test
    /*
     * 获取查询实体集合:query.getResultList()
     */
    public void testJpql2(){
        //1、创建jpql语句(SELECT u可以省去)
        String jpql = "SELECT u FROM User u WHERE u.id >?";
        //2、创建查询语句
        Query query = entityManager.createQuery(jpql);
        //3、设置查询参数,位置从1开始
        query.setParameter(1, 10l);
        //4、执行查询(返回查询的实体集合)
        List list = query.getResultList();
        for (User user : list) {
            System.out.println(user.getUserName());
        }
    }
控制台输出:
Hibernate: 
    select
       略...
Lucy
jackson
Hession

api:
query.getResultList():返回查询到的实体集合

@Test
    /*
     * 创建查询对象三种方式:2、createNamedQuery();
     * 前提:在查询实体上添加注解,并设置好name及查询语句
     * 这里需要在User实体类上添加
     * @NamedQuery(name="jpqlNamedQuery",query="SELECT u FROM User u WHERE u.id=1l")
     */
    public void testJpql3(){
        //传入的字符串即为实体类上定义的name属性
         Query query = entityManager.createNamedQuery("jpqlNamedQuery");
         User user = (User)query.getSingleResult();
         System.out.println(user.getUserInfo()); 
    }

api:
entityManager.createNamedQuery(“jpqlNamedQuery”):查询语句写在实体类上,设置好name,从而创建查询语句,这种方式在hibernate中也有,不过hibernate是把这些写在了配置文件中。

    @Test
    /*
     * 创建查询对象三种方式:3、createNativeQuery();
     */
    public void testJpqlNative(){
        String sql = "SELECT u.user_name FROM t_user u WHERE u.id=?";
        Query query = entityManager.createNativeQuery(sql);
        query.setParameter(1, 1l);
        Object result = query.getSingleResult();
        System.out.println(result); 
    }

api:
entityManager.createNativeQuery(sql):传入的是sql语句,得到的是Object对象或者泛型为Object的list。

    @Test
    /*
     * 查询部分属性然后封装为实体类
     * 默认情况下,若只查询部分属性,则将返回Object[]类型的结果.或者Object[]类型的list
     * 也可以在实体类中创建对应的构造器,然后再JPQL语句中利用对应的构造器返回实体类的对象
     */
    public void testJpql4(){
        String jpql = "SELECT u.userName,u.telephone FROM User u";
        Query query = entityManager.createQuery(jpql);
        List list = query.getResultList();
        for (Object[] objs : list) {
            for (Object object : objs) {
                System.out.println(object);
            }
        }
    }
    @Test
    public void testJpql5(){
        String jpql = "SELECT new User(u.userName,u.telephone) FROM User u";
        Query query = entityManager.createQuery(jpql);
        List list = query.getResultList();
        for (User user : list) {
            System.out.println(user.getUserName());
        }
    }

输出结果分别为:

Torra
15922222226
Torra
13922222226
Lucy
15522222226
jackson
13322222226
Hession
15822222226
Torra
Torra
Lucy
jackson
Hession

1、分页查询

    @Test
    public void testJpql6(){
        String jpql = "SELECT u FROM User u WHERE u.id>?";
        Query query = entityManager.createQuery(jpql);
        query.setParameter(1, 1l);
        //分页查询,下标1开始,查询2条
        query.setFirstResult(1);
        query.setMaxResults(2);
        List list = query.getResultList();
        for (User user : list) {
            System.out.println(user);
        }
    }

api:
query.setFirstResult(pageNum):设置分页查询下标开始位置;
query.setMaxResults(pageSize):设置分页查询记录条数;

控制台输出:
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.create_time as create_t2_2_,
        user0_.email as email3_2_,
        user0_.password as password4_2_,
        user0_.telephone as telephon5_2_,
        user0_.user_name as user_nam6_2_ 
    from
        t_user user0_ 
    where
        user0_.id>? limit ?, ?
User [id=13, userName=Lucy, password=123456, telephone=15522222226, [email protected]]
User [id=14, userName=jackson, password=123456, telephone=13322222226, email=14]

2、排序
按照id降序排列

@Test//排序
    public void testJpql7(){
        String jpql = "SELECT u FROM User u WHERE u.id>? ORDER BY u.id DESC";
        Query query = entityManager.createQuery(jpql);
        query.setParameter(1, 1l);
        List list = query.getResultList();
        for (User user : list) {
            System.out.println(user);
        }
    }

排序语句跟sql语句一样,直接使用ORDER BY 字段 排序方式。
另外Group By,having,函数,都是跟写sql语句一样。

3、DML语句
修改id为14的用户的用户名和邮箱

@Test
    public void testJpql8(){
        String jpql = "UPDATE User u SET u.userName=? , u.email=? WHERE u.id=?";
        Query query = entityManager.createQuery(jpql);
        query.setParameter(1, "LuoB");
        query.setParameter(2, "[email protected]");
        query.setParameter(3,14l);
        query.executeUpdate();
    }
控制台输出:
Hibernate: 
    update
        t_user 
    set
        user_name=?,
        email=? 
    where
        id=?

查看数据库t_user表
jpa之jpql查询_第2张图片

说到这里,感觉还是hibernate的hql和qbc查询好用,而jpa也只是hibernate的一个子集,即使jpa与spring整合了(确实可以整合)似乎也没hibernate好用,但是jpa的好用之处不在这,在于它和spring data 的结合使用,而spring data与关系型数据库结合中并没有hibernate只有jpa(有mybatis),所以要会spring data + jpa得先知道jpa,用了spring data之后就能体会到快速开发的感觉了。

你可能感兴趣的:(jpa)