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写法
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();
}
子查询:
//子查询:查询出大于平均工资的员工信息
@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<Employee> 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;
不用
------------------------------------------------------------------------------------------------------------------------------------------------
乐观锁:
乐观锁 不会锁数据,通过版本号机制