JPA JPQL语句 高级分页查询

JPA 04 — JPQL

JPQL;(掌握)

1.什么是JPQL

​ JPQL全称Java Persistence Query Language

​ ava持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式

​ jpql和sql是类似的,和sql有区别不能出现*

2.jpql原则属性的规则

​ (1).在jpql不能出现*,不能出现表名,只能出现对象别名,或者类名(类的完全限定名)

​ (2).关键字和sql里面一样的 不区分大小写

​ (3).类名和属性名要区分大小写

distinct去重

Join的SQL写法
JPA JPQL语句 高级分页查询_第1张图片

Join的JPQL写法

JPA中的JOIN和LEFT JOIN(使用SQL/JPQL对比)

sql:select * 表1 join 表2 on 条件

jpql:

​ 1.不写on子句

​ 2.模型 模型的别名 join 写前面模型别名.出来的对象属性

//查询出所有员工及部门名称【JOIN/LEFT JOIN】

@Test

public void test13() throws Exception {

  EntityManager entityManager = JPAUtils.getEntityManager();

  String jpql = "select o,d.name from Employee o left join o.department d";

  Query query = entityManager.createQuery(jpql);

  List<Object[]> list = query.getResultList();

  for (Object[] objects : list) {

​    System.out.println(Arrays.toString(objects));

  }

  System.out.println("size:" + list.size());

  entityManager.close();

}


//查询出市场部员工信息及电话
@Test
public void test14() throws Exception {
  EntityManager entityManager = JPAUtils.getEntityManager();
  String jpql = "select e,o from Phone o join o.employee e where e.department.name=?";
  Query query = entityManager.createQuery(jpql);
  query.setParameter(1, "市场部");
  List<Object[]> list = query.getResultList();
  for (Object[] objects : list) {
    System.out.println(Arrays.toString(objects));
  }
  System.out.println("size:" + list.size());
  entityManager.close();
}

聚集函数:
//查询出各个部门员工的平均工资和最高工资【使用聚集函数】  先把部门分组
@Test
public void test15() throws Exception {
  EntityManager entityManager = JPAUtils.getEntityManager();
  String jpql = "select avg(o.salary),max(o.salary) from Employee o group by o.department.name";
  Query query = entityManager.createQuery(jpql);
  List<Object[]> list = query.getResultList();
  for (Object[] objects : list) {
    System.out.println(Arrays.toString(objects));
  }
  System.out.println("size:" + list.size());
  entityManager.close();
}

//查询出各个项目参与人数报表
// 项目1 3人
// 项目2 2人
@Test
public void test16() throws Exception {
  EntityManager entityManager = JPAUtils.getEntityManager();
  //查询出各个项目参与人数(不使用聚合)
  String jpql = "select o.name,o.employees.size from Project o where o.employees.size>0";
  //查询出各个项目参与人数(使用聚合)
  jpql = "select o.name,count(e) from Project o join o.employees e group by o.name";
  Query query = entityManager.createQuery(jpql);
  List<Object[]> list = query.getResultList();
  for (Object[] objects : list) {
    System.out.println(Arrays.toString(objects));
  }
  System.out.println("size:" + list.size());
  entityManager.close();
}

子查询:

JPA JPQL语句 高级分页查询_第2张图片

//子查询:查询出大于平均工资的员工信息
@Test
public void test17() throws Exception {
  EntityManager entityManager = JPAUtils.getEntityManager();
  String jpql = "select o from Employee o where salary>(select avg(salary) from Employee)";
  Query query = entityManager.createQuery(jpql);
  List list = query.getResultList();
  for (Employee employee : list) {
    System.out.println(employee);
  }
  System.out.println("size:" + list.size());
  entityManager.close();
}

分页查询(掌握)

sql里面怎么分页:

​ select * from t_table limit beginIndex,pageSize

beginIndex:开始位置

pageSize:每页显示的条数

beginIndex = (currentPage-1)*pageSize;

分页查询
获取分页数据
@Test
public void limit() throws Exception {
  // 当前页码
  int currentPage = 2;
  // 一页显示条数
  int pageSize = 5;

  EntityManager entityManager = JPAUtils.getEntityManager();
  String jpql = "select o from Employee o";
  Query query = entityManager.createQuery(jpql);
  // 从那里开始取数据,索引从0开始
  int firstResult = (currentPage - 1) * pageSize;
  // 取多少条
  int maxResults = pageSize;
  query.setFirstResult(firstResult).setMaxResults(maxResults);
  List<Employee> list = query.getResultList();
  for (Employee employee : list) {
    System.out.println(employee);
  }
  System.out.println("size:" + list.size());
  entityManager.close();
}


//分页原理
//MySQLDialect核心代码
@Override
public String getLimitString(String sql, boolean hasOffset) {
  return sql + (hasOffset ? " limit ?, ?" : " limit ?");
}

//获取记录总数,返回类型是Long
@Test
public void count() throws Exception {
  EntityManager entityManager = JPAUtils.getEntityManager();
  String jpql = "select count(o) from Employee o"; //不能出现*
  Query query = entityManager.createQuery(jpql);
  Long result = (Long) query.getSingleResult(); //数据库原本是Integer 所以需要强转
  System.out.println("size:" + result);
  entityManager.close();
}

原生SQL查询;(掌握)

//返回对象数组
@Test
  public void test3() throws Exception {
    EntityManager entityManager = JPAUtils.getEntityManager();
    String sql = "select * from employee";
    Query query = entityManager.createNativeQuery(sql);
    List<Object[]> list = query.getResultList();
    for (Object[] objects : list) {
      System.out.println(Arrays.toString(objects));
    }
    System.out.println("size:" + list.size());
    entityManager.close();
  }




//返回模型对象
  @Test
  public void test31() throws Exception {
    EntityManager entityManager = JPAUtils.getEntityManager();
    String sql = "select * from employee";
    // 告诉hibernate把employee表转换为Employee对象
    Query query = entityManager.createNativeQuery(sql, Employee.class);
    List<Employee> list = query.getResultList();
    query.setFirstResult(3).setMaxResults(3);
    for (Employee employee : list) {
      System.out.println(employee);
    }
    System.out.println("size:" + list.size());
    entityManager.close();
  }

乐观锁;(掌握)

什么叫做事务?

​ 一组操作要么都成功 要么都失败 (事务同生共死)

事务特性;

​ ACID:

​ 原子性:事务这个单元他已经是最小单元了,不能再去分割了

​ 一致性:数据一致性,操作之前,如果金额是100,操作完之后,金额也应该是100

​ 隔离性:事务和事务之间,他们是相互隔离的,你的事务不能操作我的事务,不然会出现事务并发

​ 持久性:当前事务commit的时候,就把数据永久存储下来;

事务并发带来的问题

事务并发:

​ 第一类丢失更新 ,第二类丢失更新。第一类丢失更新和第二类丢失更新,现象是差不多

​ 第一类丢失更新:一个人投一票,另外一个人又撤销 – 投的票丢失

​ 第二类丢失更新:明明两个人都投了一票,但是只有一票有效

-----------程序可以处理第一类丢失更新第二类丢失更新

​ 脏读

​ 虚读(幻读)

不可重复读

-------- 脏读 虚读 不可重复 交给数据库处理,数据库事务隔离级别–数据库管理员dba (运维范畴)(oracle dba 2000$ 培训还–会计师)

------ 一般不建议你去修改隔离级别 除非你是数据库dba

数据库隔离级别

READ UNCOMMITTED(读未提交) 幻想读(虚读)、不可重复读和脏读都允许。

READ COMMITTED 允许幻想读,不可重复读,不允许脏读

REPEATABLE READ(repeatable) 允许幻想读,不允许不可重复读和脏读

SERIALIZABLE 幻想读、不可重复读和脏读都不允许

第一类丢失更新和第二类丢失更新

悲观锁: Lock

​ 相当于同步效果, 如果一个人操作数据的时候,先把数据锁住,另外一个人必须等待我操作完,释放锁之后,才能进行操作

​ 弊端:如果效率很低

​ 底层: 可以锁行

​ transaction;

​ begin:

​ select * from t_employee where id=1 for update;

​ …

​ update t_employee set money =money+1000;

commit;

不用

​ ------------------------------------------------------------------------------------------------------------------------------------------------

乐观锁:

​ 乐观锁 不会锁数据,通过版本号机制

如何优化JPA

经验:
  1. 使用双向一对多关联,不使用单向一对多–效率高一点
  2. 灵活使用单向多对一关联 --多方来维护效率高一点
  3. 不用一对一,用多对一取代(不要使用共享主键一对一,使用唯一外键一对一)
  4. 配置对象二级缓存(配置 Cacheable),查询缓存(jpql查询),
    没有查询条件才使用查询缓存(如果有条件命中是很低)
  5. 组合关系集合使用list(顺序,重复)–第二个项目 单据模块,多对多集合使用set
  6. 表字段要少,表关联不要怕多,有二级缓存撑腰,设计表尽量达到第三范式(外键)

JPA难在什么地方 -> 细节(练,思考)太多了,性能太难控制了(经验)

你可能感兴趣的:(个人记录)